defmodule Berrypod.SiteTest do
  use Berrypod.DataCase, async: false

  alias Berrypod.Site
  alias Berrypod.Site.SocialLink

  describe "social links CRUD" do
    test "creates a social link" do
      assert {:ok, link} =
               Site.create_social_link(%{
                 platform: "instagram",
                 url: "https://instagram.com/test"
               })

      assert link.platform == "instagram"
      assert link.url == "https://instagram.com/test"
      assert link.position == 0
    end

    test "lists social links ordered by position" do
      {:ok, _} =
        Site.create_social_link(%{platform: "twitter", url: "https://twitter.com", position: 1})

      {:ok, _} =
        Site.create_social_link(%{
          platform: "instagram",
          url: "https://instagram.com",
          position: 0
        })

      {:ok, _} =
        Site.create_social_link(%{platform: "github", url: "https://github.com", position: 2})

      links = Site.list_social_links()
      assert length(links) == 3
      assert Enum.map(links, & &1.platform) == ["instagram", "twitter", "github"]
    end

    test "updates a social link" do
      {:ok, link} = Site.create_social_link(%{platform: "custom", url: ""})

      {:ok, updated} =
        Site.update_social_link(link, %{url: "https://example.com", platform: "website"})

      assert updated.url == "https://example.com"
      assert updated.platform == "website"
    end

    test "deletes a social link" do
      {:ok, link} =
        Site.create_social_link(%{platform: "instagram", url: "https://instagram.com"})

      assert {:ok, _} = Site.delete_social_link(link)
      assert Site.list_social_links() == []
    end

    test "reorders social links" do
      {:ok, a} =
        Site.create_social_link(%{
          platform: "instagram",
          url: "https://instagram.com",
          position: 0
        })

      {:ok, b} =
        Site.create_social_link(%{platform: "twitter", url: "https://twitter.com", position: 1})

      {:ok, c} =
        Site.create_social_link(%{platform: "github", url: "https://github.com", position: 2})

      # Reorder: github, instagram, twitter
      Site.reorder_social_links([c.id, a.id, b.id])

      links = Site.list_social_links()
      assert Enum.map(links, & &1.platform) == ["github", "instagram", "twitter"]
    end
  end

  describe "social_links_for_shop/0" do
    test "returns links formatted for shop components" do
      {:ok, _} =
        Site.create_social_link(%{
          platform: "instagram",
          url: "https://instagram.com/test",
          position: 0
        })

      [link] = Site.social_links_for_shop()
      assert link.platform == :instagram
      assert link.url == "https://instagram.com/test"
      assert link.label == "Instagram"
    end

    test "filters out links with empty URLs" do
      {:ok, _} =
        Site.create_social_link(%{
          platform: "instagram",
          url: "https://instagram.com",
          position: 0
        })

      {:ok, _} = Site.create_social_link(%{platform: "custom", url: "", position: 1})
      {:ok, _} = Site.create_social_link(%{platform: "twitter", url: nil, position: 2})

      links = Site.social_links_for_shop()
      assert length(links) == 1
      assert hd(links).platform == :instagram
    end
  end

  describe "SocialLink.normalize_url/1" do
    test "trims whitespace" do
      assert SocialLink.normalize_url("  https://example.com  ") == "https://example.com"
    end

    test "adds https:// to bare domains" do
      assert SocialLink.normalize_url("example.com") == "https://example.com"
      assert SocialLink.normalize_url("github.com/user") == "https://github.com/user"
    end

    test "preserves http://" do
      assert SocialLink.normalize_url("http://example.com") == "http://example.com"
    end

    test "preserves https://" do
      assert SocialLink.normalize_url("https://example.com") == "https://example.com"
    end

    test "preserves app deep links" do
      assert SocialLink.normalize_url("tg://resolve?domain=channel") ==
               "tg://resolve?domain=channel"

      assert SocialLink.normalize_url("spotify:track:123") == "spotify:track:123"
      assert SocialLink.normalize_url("rss://feed.example.com") == "rss://feed.example.com"
    end

    test "preserves mailto: and tel:" do
      assert SocialLink.normalize_url("mailto:user@example.com") == "mailto:user@example.com"
      assert SocialLink.normalize_url("tel:+1234567890") == "tel:+1234567890"
    end

    test "handles nil and empty strings" do
      assert SocialLink.normalize_url(nil) == nil
      assert SocialLink.normalize_url("") == ""
      assert SocialLink.normalize_url("   ") == ""
    end
  end

  describe "SocialLink.detect_platform/1" do
    test "detects common platforms from URLs" do
      assert SocialLink.detect_platform("https://github.com/user") == "github"
      assert SocialLink.detect_platform("https://twitter.com/user") == "twitter"
      assert SocialLink.detect_platform("https://x.com/user") == "twitter"
      assert SocialLink.detect_platform("https://instagram.com/user") == "instagram"
      assert SocialLink.detect_platform("https://bsky.app/profile/user") == "bluesky"
      assert SocialLink.detect_platform("https://mastodon.social/@user") == "mastodon"
    end

    test "handles www prefix" do
      assert SocialLink.detect_platform("https://www.github.com/user") == "github"
      assert SocialLink.detect_platform("https://www.youtube.com/watch?v=123") == "youtube"
    end

    test "detects subdomain-based platforms" do
      assert SocialLink.detect_platform("https://artist.bandcamp.com") == "bandcamp"
      assert SocialLink.detect_platform("https://writer.substack.com") == "substack"
      assert SocialLink.detect_platform("https://user.tumblr.com") == "tumblr"
    end

    test "detects platforms from URI schemes" do
      assert SocialLink.detect_platform("tg://resolve?domain=channel") == "telegram"
      assert SocialLink.detect_platform("spotify:track:123") == "spotify"
      assert SocialLink.detect_platform("rss://feed.example.com") == "rss"
      assert SocialLink.detect_platform("discord://discord.com/channels/123") == "discord"
    end

    test "normalizes URLs before detection" do
      assert SocialLink.detect_platform("github.com/user") == "github"
      assert SocialLink.detect_platform("  twitter.com/user  ") == "twitter"
    end

    test "returns custom for unknown domains" do
      assert SocialLink.detect_platform("https://example.com") == "custom"
      assert SocialLink.detect_platform("https://my-personal-site.org") == "custom"
    end

    test "returns nil for invalid input" do
      assert SocialLink.detect_platform("") == nil
      assert SocialLink.detect_platform(nil) == nil
    end
  end

  describe "SocialLink changeset validation" do
    test "requires platform" do
      changeset = SocialLink.changeset(%SocialLink{}, %{url: "https://example.com"})
      assert %{platform: ["can't be blank"]} = errors_on(changeset)
    end

    test "validates platform is in allowed list" do
      changeset = SocialLink.changeset(%SocialLink{}, %{platform: "invalid_platform"})
      assert %{platform: ["is invalid"]} = errors_on(changeset)
    end

    test "allows empty URL" do
      changeset = SocialLink.changeset(%SocialLink{}, %{platform: "custom", url: ""})
      assert changeset.valid?
    end

    test "allows nil URL" do
      changeset = SocialLink.changeset(%SocialLink{}, %{platform: "custom", url: nil})
      assert changeset.valid?
    end

    test "validates URL has a scheme" do
      changeset = SocialLink.changeset(%SocialLink{}, %{platform: "custom", url: "no-scheme.com"})
      assert %{url: ["must be a valid URL"]} = errors_on(changeset)
    end

    test "accepts URLs with any scheme" do
      changeset =
        SocialLink.changeset(%SocialLink{}, %{platform: "telegram", url: "tg://resolve"})

      assert changeset.valid?

      changeset =
        SocialLink.changeset(%SocialLink{}, %{platform: "rss", url: "rss://feed.example.com"})

      assert changeset.valid?
    end
  end

  describe "announcement settings" do
    test "stores and retrieves announcement text" do
      Site.set_announcement_text("Free shipping!")
      assert Site.announcement_text() == "Free shipping!"
    end

    test "stores and retrieves announcement link" do
      Site.set_announcement_link("/delivery")
      assert Site.announcement_link() == "/delivery"
    end

    test "stores and retrieves announcement style" do
      Site.set_announcement_style("sale")
      assert Site.announcement_style() == "sale"
    end

    test "defaults to empty string for text and link" do
      assert Site.announcement_text() == ""
      assert Site.announcement_link() == ""
    end

    test "defaults to info for style" do
      assert Site.announcement_style() == "info"
    end
  end

  describe "footer settings" do
    test "stores and retrieves footer about text" do
      Site.set_footer_about("About us blurb")
      assert Site.footer_about() == "About us blurb"
    end

    test "stores and retrieves footer copyright" do
      Site.set_footer_copyright("© 2024 My Shop")
      assert Site.footer_copyright() == "© 2024 My Shop"
    end

    test "stores and retrieves newsletter visibility" do
      Site.set_show_newsletter(false)
      assert Site.show_newsletter?() == false

      Site.set_show_newsletter(true)
      assert Site.show_newsletter?() == true
    end
  end

  describe "nav_items_for_shop/1" do
    test "resolves system page URLs through R module" do
      # Set a custom URL for the about page
      {:ok, _} = Berrypod.Pages.update_page_url_slug("about", "our-story")

      # Create a nav item pointing to /about (the default URL)
      {:ok, _} = Site.create_nav_item(%{location: "header", label: "About", url: "/about"})

      # The resolved URL should use the custom slug
      [item] = Site.nav_items_for_shop(:header)
      assert item["href"] == "/our-story"
    end

    test "resolves home page URL" do
      {:ok, _} = Site.create_nav_item(%{location: "header", label: "Home", url: "/"})

      [item] = Site.nav_items_for_shop(:header)
      assert item["href"] == "/"
    end

    test "preserves external URLs" do
      {:ok, _} =
        Site.create_nav_item(%{
          location: "header",
          label: "External",
          url: "https://example.com"
        })

      [item] = Site.nav_items_for_shop(:header)
      assert item["href"] == "https://example.com"
    end

    test "preserves special routes like /collections/all" do
      {:ok, _} =
        Site.create_nav_item(%{
          location: "header",
          label: "Shop",
          url: "/collections/all"
        })

      [item] = Site.nav_items_for_shop(:header)
      assert item["href"] == "/collections/all"
    end
  end
end
