defmodule Berrypod.LegalPagesTest do
  use Berrypod.DataCase, async: true

  alias Berrypod.LegalPages
  alias Berrypod.Settings

  # ---------------------------------------------------------------------------
  # Helpers
  # ---------------------------------------------------------------------------

  defp has_heading?(blocks, text) do
    Enum.any?(blocks, &(&1.type == :heading and &1.text == text))
  end

  defp has_text_containing?(blocks, fragment) do
    Enum.any?(blocks, fn block ->
      case block do
        %{text: text} when is_binary(text) -> String.contains?(text, fragment)
        %{items: items} -> Enum.any?(items, &String.contains?(&1, fragment))
        _ -> false
      end
    end)
  end

  # ---------------------------------------------------------------------------
  # privacy_content/0
  # ---------------------------------------------------------------------------

  describe "privacy_content/0" do
    test "returns a list of blocks with :lead as the first" do
      blocks = LegalPages.privacy_content()

      assert is_list(blocks)
      assert hd(blocks).type == :lead
    end

    test "last block is a :closing disclaimer" do
      blocks = LegalPages.privacy_content()

      assert List.last(blocks).type == :closing
      assert String.contains?(List.last(blocks).text, "legal advice")
    end

    test "always includes core sections" do
      blocks = LegalPages.privacy_content()

      assert has_heading?(blocks, "What we collect")
      assert has_heading?(blocks, "Payment")
      assert has_heading?(blocks, "Cookies")
      assert has_heading?(blocks, "Third parties")
      assert has_heading?(blocks, "Your rights")
      assert has_heading?(blocks, "Contact")
    end

    test "includes PECR cart recovery wording for GB shop" do
      Settings.put_setting("shop_country", "GB")
      Settings.set_abandoned_cart_recovery(true)

      blocks = LegalPages.privacy_content()

      assert has_heading?(blocks, "Cart recovery")
      assert has_text_containing?(blocks, "PECR")
      assert has_text_containing?(blocks, "Regulation 22")
    end

    test "includes GDPR legitimate interests wording for EU shop" do
      Settings.put_setting("shop_country", "DE")
      Settings.set_abandoned_cart_recovery(true)

      blocks = LegalPages.privacy_content()

      assert has_heading?(blocks, "Cart recovery")
      assert has_text_containing?(blocks, "Article 6(1)(f)")
      refute has_text_containing?(blocks, "PECR")
    end

    test "includes generic cart recovery wording for non-UK/EU shop" do
      Settings.put_setting("shop_country", "US")
      Settings.set_abandoned_cart_recovery(true)

      blocks = LegalPages.privacy_content()

      assert has_heading?(blocks, "Cart recovery")
      refute has_text_containing?(blocks, "PECR")
      refute has_text_containing?(blocks, "Article 6(1)(f)")
    end

    test "omits cart recovery section when feature is disabled" do
      Settings.set_abandoned_cart_recovery(false)

      blocks = LegalPages.privacy_content()

      refute has_heading?(blocks, "Cart recovery")
    end

    test "includes newsletter section when enabled" do
      Settings.put_setting("newsletter_enabled", true, "boolean")

      blocks = LegalPages.privacy_content()

      assert has_heading?(blocks, "Newsletter")
    end

    test "omits newsletter section when disabled" do
      Settings.put_setting("newsletter_enabled", false, "boolean")

      blocks = LegalPages.privacy_content()

      refute has_heading?(blocks, "Newsletter")
    end

    test "includes jurisdiction language in lead for GB" do
      Settings.put_setting("shop_country", "GB")

      blocks = LegalPages.privacy_content()

      assert has_text_containing?(blocks, "UK GDPR")
      assert has_text_containing?(blocks, "PECR")
    end

    test "includes GDPR jurisdiction language for EU country" do
      Settings.put_setting("shop_country", "FR")

      blocks = LegalPages.privacy_content()

      assert has_text_containing?(blocks, "EU General Data Protection Regulation")
    end

    test "includes contact email when set" do
      Settings.put_setting("contact_email", "hello@example.com")

      blocks = LegalPages.privacy_content()

      assert has_text_containing?(blocks, "hello@example.com")
    end
  end

  # ---------------------------------------------------------------------------
  # delivery_content/0
  # ---------------------------------------------------------------------------

  describe "delivery_content/0" do
    test "returns a list of blocks with :lead as the first" do
      blocks = LegalPages.delivery_content()

      assert is_list(blocks)
      assert hd(blocks).type == :lead
    end

    test "always includes returns, cancellations, and production sections" do
      blocks = LegalPages.delivery_content()

      assert has_heading?(blocks, "Production time")
      assert has_heading?(blocks, "Returns & exchanges")
      assert has_heading?(blocks, "Cancellations")
    end

    test "cites Consumer Contracts Regulations in returns section" do
      blocks = LegalPages.delivery_content()

      assert has_text_containing?(blocks, "Consumer Contracts")
      assert has_text_containing?(blocks, "Regulation 28(1)(b)")
    end

    test "cites Consumer Rights Act for defective goods" do
      blocks = LegalPages.delivery_content()

      assert has_text_containing?(blocks, "Consumer Rights Act 2015")
    end

    test "handles empty shipping countries gracefully" do
      # No shipping rates seeded — list will be empty in test
      blocks = LegalPages.delivery_content()

      # Should not crash and should include a fallback paragraph
      assert is_list(blocks)
      assert has_text_containing?(blocks, "worldwide")
    end

    test "last block is a :closing disclaimer" do
      blocks = LegalPages.delivery_content()

      assert List.last(blocks).type == :closing
    end
  end

  # ---------------------------------------------------------------------------
  # terms_content/0
  # ---------------------------------------------------------------------------

  describe "terms_content/0" do
    test "returns a list of blocks with :lead as the first" do
      blocks = LegalPages.terms_content()

      assert is_list(blocks)
      assert hd(blocks).type == :lead
    end

    test "always includes core sections" do
      blocks = LegalPages.terms_content()

      assert has_heading?(blocks, "Products")
      assert has_heading?(blocks, "Payment")
      assert has_heading?(blocks, "Returns")
      assert has_heading?(blocks, "Governing law")
      assert has_heading?(blocks, "Changes")
    end

    test "governing law is English law for GB shop" do
      Settings.put_setting("shop_country", "GB")

      blocks = LegalPages.terms_content()

      assert has_text_containing?(blocks, "English law")
    end

    test "governing law references EU regulations for EU shop" do
      Settings.put_setting("shop_country", "DE")

      blocks = LegalPages.terms_content()

      assert has_text_containing?(blocks, "EU regulations")
    end

    test "includes VAT clause when vat_enabled is true" do
      Settings.put_setting("vat_enabled", true, "boolean")

      blocks = LegalPages.terms_content()

      assert has_text_containing?(blocks, "VAT")
    end

    test "omits VAT clause when vat_enabled is false" do
      Settings.put_setting("vat_enabled", false, "boolean")

      blocks = LegalPages.terms_content()

      refute has_text_containing?(blocks, "VAT")
    end

    test "includes shop name in lead" do
      Settings.put_setting("shop_name", "Petal & Ink")

      blocks = LegalPages.terms_content()

      assert has_text_containing?(blocks, "Petal & Ink")
    end

    test "last block is a :closing disclaimer" do
      blocks = LegalPages.terms_content()

      assert List.last(blocks).type == :closing
    end
  end

  # ---------------------------------------------------------------------------
  # regenerate_legal_content/1
  # ---------------------------------------------------------------------------

  describe "regenerate_legal_content/1" do
    test "returns a non-empty string for privacy" do
      result = LegalPages.regenerate_legal_content("privacy")
      assert is_binary(result)
      assert String.length(result) > 100
    end

    test "returns a non-empty string for delivery" do
      result = LegalPages.regenerate_legal_content("delivery")
      assert is_binary(result)
      assert String.length(result) > 100
    end

    test "returns a non-empty string for terms" do
      result = LegalPages.regenerate_legal_content("terms")
      assert is_binary(result)
      assert String.length(result) > 100
    end
  end

  # ---------------------------------------------------------------------------
  # rich_text_to_plain/1
  # ---------------------------------------------------------------------------

  describe "rich_text_to_plain/1" do
    test "converts headings to markdown-style" do
      blocks = [%{type: :heading, text: "Hello"}]
      assert LegalPages.rich_text_to_plain(blocks) == "## Hello"
    end

    test "converts paragraphs as-is" do
      blocks = [%{type: :paragraph, text: "Some text here."}]
      assert LegalPages.rich_text_to_plain(blocks) == "Some text here."
    end

    test "converts lists to bullet points" do
      blocks = [%{type: :list, items: ["One", "Two", "Three"]}]
      assert LegalPages.rich_text_to_plain(blocks) == "• One\n• Two\n• Three"
    end

    test "converts lead blocks" do
      blocks = [%{type: :lead, text: "Important intro"}]
      assert LegalPages.rich_text_to_plain(blocks) == "Important intro"
    end

    test "converts updated_at blocks" do
      blocks = [%{type: :updated_at, date: "28 February 2026"}]
      assert LegalPages.rich_text_to_plain(blocks) == "Last updated: 28 February 2026"
    end

    test "joins multiple blocks with double newlines" do
      blocks = [
        %{type: :heading, text: "Title"},
        %{type: :paragraph, text: "Body text."}
      ]

      assert LegalPages.rich_text_to_plain(blocks) == "## Title\n\nBody text."
    end

    test "skips unknown block types" do
      blocks = [
        %{type: :heading, text: "Title"},
        %{type: :unknown_thing, data: "whatever"},
        %{type: :paragraph, text: "Body."}
      ]

      assert LegalPages.rich_text_to_plain(blocks) == "## Title\n\nBody."
    end
  end

  # ---------------------------------------------------------------------------
  # legal_slug?/1
  # ---------------------------------------------------------------------------

  describe "legal_slug?/1" do
    test "returns true for legal page slugs" do
      assert LegalPages.legal_slug?("privacy")
      assert LegalPages.legal_slug?("delivery")
      assert LegalPages.legal_slug?("terms")
    end

    test "returns false for non-legal slugs" do
      refute LegalPages.legal_slug?("home")
      refute LegalPages.legal_slug?("about")
      refute LegalPages.legal_slug?("contact")
    end
  end
end
