defmodule BerrypodWeb.Admin.PagesTest do
  use BerrypodWeb.ConnCase, async: false

  import Phoenix.LiveViewTest
  import Berrypod.AccountsFixtures

  alias Berrypod.Pages
  alias Berrypod.Pages.PageCache

  setup do
    PageCache.invalidate_all()
    user = user_fixture()
    %{user: user}
  end

  describe "unauthenticated" do
    test "redirects to login", %{conn: conn} do
      {:error, redirect} = live(conn, ~p"/admin/pages")
      assert {:redirect, %{to: path}} = redirect
      assert path == ~p"/users/log-in"
    end
  end

  describe "page list" do
    setup %{conn: conn, user: user} do
      %{conn: log_in_user(conn, user)}
    end

    test "renders page list with groups", %{conn: conn} do
      {:ok, _view, html} = live(conn, ~p"/admin/pages")

      assert html =~ "Pages"
      assert html =~ "Marketing"
      assert html =~ "Legal"
      assert html =~ "Shop"
      assert html =~ "Orders"
      assert html =~ "System"
    end

    test "shows all 14 pages", %{conn: conn} do
      {:ok, view, _html} = live(conn, ~p"/admin/pages")

      assert has_element?(view, ".page-card-title", "Home page")
      assert has_element?(view, ".page-card-title", "About")
      assert has_element?(view, ".page-card-title", "Contact")
      assert has_element?(view, ".page-card-title", "Product page")
      assert has_element?(view, ".page-card-title", "Error")
    end

    test "shows block count per page", %{conn: conn} do
      {:ok, view, _html} = live(conn, ~p"/admin/pages")

      # Home has 4 default blocks
      assert has_element?(view, ".page-card-meta", "4 blocks")
    end

    test "links to editor", %{conn: conn} do
      {:ok, view, _html} = live(conn, ~p"/admin/pages")

      view
      |> element("a[href='/admin/pages/home']")
      |> render_click()

      assert_redirect(view, ~p"/admin/pages/home")
    end
  end

  describe "page editor" do
    setup %{conn: conn, user: user} do
      %{conn: log_in_user(conn, user)}
    end

    test "renders editor with blocks", %{conn: conn} do
      {:ok, view, _html} = live(conn, ~p"/admin/pages/home")

      assert has_element?(view, ".block-card-name", "Hero banner")
      assert has_element?(view, ".block-card-name", "Category navigation")
      assert has_element?(view, ".block-card-name", "Featured products")
      assert has_element?(view, ".block-card-name", "Image + text")
    end

    test "shows position numbers", %{conn: conn} do
      {:ok, view, _html} = live(conn, ~p"/admin/pages/home")

      assert has_element?(view, ".block-card-position", "1")
      assert has_element?(view, ".block-card-position", "4")
    end

    test "shows back link", %{conn: conn} do
      {:ok, view, _html} = live(conn, ~p"/admin/pages/home")

      assert has_element?(view, "a[href='/admin/pages']", "Pages")
    end

    test "move block up reorders blocks", %{conn: conn} do
      {:ok, view, _html} = live(conn, ~p"/admin/pages/home")

      # Get the second block (category_nav) and move it up
      page = Pages.get_page("home")
      second_block = Enum.at(page.blocks, 1)

      render_click(view, "move_up", %{"id" => second_block["id"]})

      # The ARIA live region announces the move
      assert has_element?(view, "[aria-live='polite']", "Category navigation moved to position 1")
    end

    test "move block down reorders blocks", %{conn: conn} do
      {:ok, view, _html} = live(conn, ~p"/admin/pages/home")

      page = Pages.get_page("home")
      first_block = Enum.at(page.blocks, 0)

      render_click(view, "move_down", %{"id" => first_block["id"]})

      # Hero banner should now be at position 2
      assert has_element?(view, "[aria-live='polite']", "Hero banner moved to position 2")
    end

    test "move up disabled for first block", %{conn: conn} do
      {:ok, view, _html} = live(conn, ~p"/admin/pages/home")

      page = Pages.get_page("home")
      first_block = Enum.at(page.blocks, 0)

      assert has_element?(
               view,
               "button[phx-value-id='#{first_block["id"]}'][phx-click='move_up'][disabled]"
             )
    end

    test "move down disabled for last block", %{conn: conn} do
      {:ok, view, _html} = live(conn, ~p"/admin/pages/home")

      page = Pages.get_page("home")
      last_block = Enum.at(page.blocks, -1)

      assert has_element?(
               view,
               "button[phx-value-id='#{last_block["id"]}'][phx-click='move_down'][disabled]"
             )
    end

    test "remove block", %{conn: conn} do
      {:ok, view, _html} = live(conn, ~p"/admin/pages/home")

      page = Pages.get_page("home")
      block = Enum.at(page.blocks, 1)

      render_click(view, "remove_block", %{"id" => block["id"]})

      refute has_element?(view, ".block-card-name", "Category navigation")
      assert has_element?(view, ".block-card-position", "3")
      refute has_element?(view, ".block-card-position", "4")
    end

    test "duplicate block", %{conn: conn} do
      {:ok, view, _html} = live(conn, ~p"/admin/pages/home")

      page = Pages.get_page("home")
      block = Enum.at(page.blocks, 0)

      render_click(view, "duplicate_block", %{"id" => block["id"]})

      # Should now have 5 blocks (position 5 exists)
      assert has_element?(view, ".block-card-position", "5")
      assert has_element?(view, "[aria-live='polite']", "Hero banner duplicated")
    end

    test "add block via picker", %{conn: conn} do
      {:ok, view, _html} = live(conn, ~p"/admin/pages/home")

      render_click(view, "show_picker")
      assert has_element?(view, ".block-picker")

      render_click(view, "add_block", %{"type" => "trust_badges"})

      assert has_element?(view, ".block-card-name", "Trust badges")
      refute has_element?(view, ".block-picker")
    end

    test "picker filter narrows results", %{conn: conn} do
      {:ok, view, _html} = live(conn, ~p"/admin/pages/home")

      render_click(view, "show_picker")
      render_keyup(view, "filter_picker", %{"value" => "hero"})

      assert has_element?(view, ".block-picker-item", "Hero banner")
      refute has_element?(view, ".block-picker-item", "Trust badges")
    end

    test "picker only shows blocks allowed on page", %{conn: conn} do
      {:ok, view, _html} = live(conn, ~p"/admin/pages/home")

      render_click(view, "show_picker")

      assert has_element?(view, ".block-picker-item", "Hero banner")
      refute has_element?(view, ".block-picker-item", "Product hero")
      refute has_element?(view, ".block-picker-item", "Cart items")
    end

    test "save persists blocks", %{conn: conn} do
      {:ok, view, _html} = live(conn, ~p"/admin/pages/home")

      page = Pages.get_page("home")
      block = Enum.at(page.blocks, 1)
      render_click(view, "remove_block", %{"id" => block["id"]})

      render_click(view, "save")

      assert has_element?(view, ".admin-inline-feedback-saved")

      saved = Pages.get_page("home")
      assert length(saved.blocks) == 3
      types = Enum.map(saved.blocks, & &1["type"])
      refute "category_nav" in types
    end

    test "reset to defaults restores original blocks", %{conn: conn} do
      {:ok, _} =
        Pages.save_page("home", %{
          title: "Home page",
          blocks: [%{"id" => "blk_test", "type" => "hero", "settings" => %{}}]
        })

      {:ok, view, _html} = live(conn, ~p"/admin/pages/home")

      # Should show only 1 block
      assert has_element?(view, ".block-card-position", "1")
      refute has_element?(view, ".block-card-position", "2")

      render_click(view, "reset_defaults")

      assert render(view) =~ "Page reset to defaults"
      # Should now have 4 default blocks
      assert has_element?(view, ".block-card-position", "4")
    end

    test "dirty flag appears after changes", %{conn: conn} do
      {:ok, view, _html} = live(conn, ~p"/admin/pages/home")

      refute has_element?(view, ".admin-badge-warning", "Unsaved changes")

      page = Pages.get_page("home")
      block = Enum.at(page.blocks, 0)
      render_click(view, "move_down", %{"id" => block["id"]})

      assert has_element?(view, ".admin-badge-warning", "Unsaved changes")
    end

    test "dirty flag clears after save", %{conn: conn} do
      {:ok, view, _html} = live(conn, ~p"/admin/pages/home")

      page = Pages.get_page("home")
      block = Enum.at(page.blocks, 0)
      render_click(view, "move_down", %{"id" => block["id"]})
      assert has_element?(view, ".admin-badge-warning")

      render_click(view, "save")
      refute has_element?(view, ".admin-badge-warning")
    end

    test "save button disabled when not dirty", %{conn: conn} do
      {:ok, view, _html} = live(conn, ~p"/admin/pages/home")

      assert has_element?(view, "button[disabled]", "Save")
    end
  end

  describe "undo and redo" do
    setup %{conn: conn, user: user} do
      %{conn: log_in_user(conn, user)}
    end

    test "undo reverts the last change", %{conn: conn} do
      {:ok, view, _html} = live(conn, ~p"/admin/pages/home")

      page = Pages.get_page("home")
      block = Enum.at(page.blocks, 1)
      render_click(view, "remove_block", %{"id" => block["id"]})

      # Block should be gone
      refute has_element?(view, ".block-card-name", "Category navigation")

      # Undo
      render_click(view, "undo")

      # Block should be back
      assert has_element?(view, ".block-card-name", "Category navigation")
      assert has_element?(view, "[aria-live='polite']", "Undone")
    end

    test "redo restores an undone change", %{conn: conn} do
      {:ok, view, _html} = live(conn, ~p"/admin/pages/home")

      page = Pages.get_page("home")
      block = Enum.at(page.blocks, 1)
      render_click(view, "remove_block", %{"id" => block["id"]})
      render_click(view, "undo")

      assert has_element?(view, ".block-card-name", "Category navigation")

      render_click(view, "redo")

      refute has_element?(view, ".block-card-name", "Category navigation")
      assert has_element?(view, "[aria-live='polite']", "Redone")
    end

    test "new mutation clears redo stack", %{conn: conn} do
      {:ok, view, _html} = live(conn, ~p"/admin/pages/home")

      page = Pages.get_page("home")
      hero = Enum.at(page.blocks, 0)
      cat_nav = Enum.at(page.blocks, 1)

      # Make a change, undo, then make a different change
      render_click(view, "remove_block", %{"id" => cat_nav["id"]})
      render_click(view, "undo")
      render_click(view, "move_down", %{"id" => hero["id"]})

      # Redo should do nothing (stack was cleared)
      render_click(view, "redo")

      # Hero should still be at position 2 (the move_down result)
      assert has_element?(view, "[aria-live='polite']", "Hero banner moved to position 2")
    end

    test "undo all the way back clears dirty flag", %{conn: conn} do
      {:ok, view, _html} = live(conn, ~p"/admin/pages/home")

      page = Pages.get_page("home")
      hero = Enum.at(page.blocks, 0)
      render_click(view, "move_down", %{"id" => hero["id"]})

      assert has_element?(view, ".admin-badge-warning", "Unsaved changes")

      render_click(view, "undo")

      refute has_element?(view, ".admin-badge-warning", "Unsaved changes")
    end

    test "undo when history empty does nothing", %{conn: conn} do
      {:ok, view, _html} = live(conn, ~p"/admin/pages/home")

      # No changes made, undo should be fine
      render_click(view, "undo")

      # Should still render normally
      assert has_element?(view, ".block-card-name", "Hero banner")
    end

    test "undo/redo buttons reflect stack state", %{conn: conn} do
      {:ok, view, _html} = live(conn, ~p"/admin/pages/home")

      # Initially both disabled
      assert has_element?(view, "button[phx-click='undo'][disabled]")
      assert has_element?(view, "button[phx-click='redo'][disabled]")

      # Make a change
      page = Pages.get_page("home")
      hero = Enum.at(page.blocks, 0)
      render_click(view, "move_down", %{"id" => hero["id"]})

      # Undo enabled, redo still disabled
      refute has_element?(view, "button[phx-click='undo'][disabled]")
      assert has_element?(view, "button[phx-click='redo'][disabled]")

      # Undo
      render_click(view, "undo")

      # Undo disabled again, redo now enabled
      assert has_element?(view, "button[phx-click='undo'][disabled]")
      refute has_element?(view, "button[phx-click='redo'][disabled]")
    end
  end

  describe "page editor for page-specific pages" do
    setup %{conn: conn, user: user} do
      %{conn: log_in_user(conn, user)}
    end

    test "PDP editor shows PDP blocks", %{conn: conn} do
      {:ok, view, _html} = live(conn, ~p"/admin/pages/pdp")

      assert has_element?(view, ".block-card-name", "Breadcrumb")
      assert has_element?(view, ".block-card-name", "Product hero")
      assert has_element?(view, ".block-card-name", "Trust badges")
    end

    test "PDP picker shows PDP-specific blocks", %{conn: conn} do
      {:ok, view, _html} = live(conn, ~p"/admin/pages/pdp")

      render_click(view, "show_picker")

      assert has_element?(view, ".block-picker-item", "Product hero")
      assert has_element?(view, ".block-picker-item", "Hero banner")
      refute has_element?(view, ".block-picker-item", "Cart items")
    end

    test "error page editor works", %{conn: conn} do
      {:ok, view, _html} = live(conn, ~p"/admin/pages/error")

      assert has_element?(view, ".block-card-name", "Hero banner")
      assert has_element?(view, ".block-card-name", "Featured products")
    end
  end

  describe "block settings editing" do
    setup %{conn: conn, user: user} do
      %{conn: log_in_user(conn, user)}
    end

    test "edit button shown only for blocks with settings", %{conn: conn} do
      {:ok, view, _html} = live(conn, ~p"/admin/pages/home")

      page = Pages.get_page("home")
      hero = Enum.at(page.blocks, 0)
      category_nav = Enum.at(page.blocks, 1)

      # Hero has settings — edit button present
      assert has_element?(view, "#block-edit-btn-#{hero["id"]}")

      # Category nav has no settings — no edit button
      refute has_element?(view, "#block-edit-btn-#{category_nav["id"]}")
    end

    test "toggle expand shows settings form", %{conn: conn} do
      {:ok, view, _html} = live(conn, ~p"/admin/pages/home")

      page = Pages.get_page("home")
      hero = Enum.at(page.blocks, 0)

      # Settings panel not visible initially
      refute has_element?(view, "#block-settings-#{hero["id"]}")

      # Click edit to expand
      render_click(view, "toggle_expand", %{"id" => hero["id"]})

      # Settings panel now visible
      assert has_element?(view, "#block-settings-#{hero["id"]}")
      assert has_element?(view, "[aria-live='polite']", "Hero banner settings expanded")
    end

    test "toggle collapse hides settings form", %{conn: conn} do
      {:ok, view, _html} = live(conn, ~p"/admin/pages/home")

      page = Pages.get_page("home")
      hero = Enum.at(page.blocks, 0)

      # Expand then collapse
      render_click(view, "toggle_expand", %{"id" => hero["id"]})
      assert has_element?(view, "#block-settings-#{hero["id"]}")

      render_click(view, "toggle_expand", %{"id" => hero["id"]})
      refute has_element?(view, "#block-settings-#{hero["id"]}")
      assert has_element?(view, "[aria-live='polite']", "Hero banner settings collapsed")
    end

    test "aria-expanded reflects toggle state", %{conn: conn} do
      {:ok, view, _html} = live(conn, ~p"/admin/pages/home")

      page = Pages.get_page("home")
      hero = Enum.at(page.blocks, 0)

      assert has_element?(view, "#block-edit-btn-#{hero["id"]}[aria-expanded='false']")

      render_click(view, "toggle_expand", %{"id" => hero["id"]})

      assert has_element?(view, "#block-edit-btn-#{hero["id"]}[aria-expanded='true']")
    end

    test "settings form renders fields from schema", %{conn: conn} do
      {:ok, view, _html} = live(conn, ~p"/admin/pages/home")

      page = Pages.get_page("home")
      hero = Enum.at(page.blocks, 0)

      render_click(view, "toggle_expand", %{"id" => hero["id"]})

      # Hero has text fields: title, description, cta_text, etc.
      assert has_element?(view, "#block-#{hero["id"]}-title")
      assert has_element?(view, "#block-#{hero["id"]}-description")
      assert has_element?(view, "#block-#{hero["id"]}-cta_text")
      # And a select field: variant
      assert has_element?(view, "#block-#{hero["id"]}-variant")
    end

    test "editing settings updates working state and sets dirty", %{conn: conn} do
      {:ok, view, _html} = live(conn, ~p"/admin/pages/home")

      page = Pages.get_page("home")
      hero = Enum.at(page.blocks, 0)

      render_click(view, "toggle_expand", %{"id" => hero["id"]})

      # Edit the title
      render_change(view, "update_block_settings", %{
        "block_id" => hero["id"],
        "block_settings" => %{"title" => "New hero title"}
      })

      # Dirty flag should appear
      assert has_element?(view, ".admin-badge-warning", "Unsaved changes")
    end

    test "edited settings persist after save", %{conn: conn} do
      {:ok, view, _html} = live(conn, ~p"/admin/pages/home")

      page = Pages.get_page("home")
      hero = Enum.at(page.blocks, 0)

      render_click(view, "toggle_expand", %{"id" => hero["id"]})

      render_change(view, "update_block_settings", %{
        "block_id" => hero["id"],
        "block_settings" => %{"title" => "Updated title", "description" => "Updated desc"}
      })

      render_click(view, "save")

      saved = Pages.get_page("home")
      saved_hero = Enum.find(saved.blocks, &(&1["type"] == "hero"))
      assert saved_hero["settings"]["title"] == "Updated title"
      assert saved_hero["settings"]["description"] == "Updated desc"
    end

    test "number fields are coerced to integers", %{conn: conn} do
      {:ok, view, _html} = live(conn, ~p"/admin/pages/home")

      page = Pages.get_page("home")
      featured = Enum.find(page.blocks, &(&1["type"] == "featured_products"))

      render_click(view, "toggle_expand", %{"id" => featured["id"]})

      render_change(view, "update_block_settings", %{
        "block_id" => featured["id"],
        "block_settings" => %{"product_count" => "4"}
      })

      render_click(view, "save")

      saved = Pages.get_page("home")
      saved_featured = Enum.find(saved.blocks, &(&1["type"] == "featured_products"))
      assert saved_featured["settings"]["product_count"] == 4
    end

    test "select fields render with options", %{conn: conn} do
      {:ok, view, _html} = live(conn, ~p"/admin/pages/home")

      page = Pages.get_page("home")
      hero = Enum.at(page.blocks, 0)

      render_click(view, "toggle_expand", %{"id" => hero["id"]})

      html = render(view)
      # Variant select should have the expected options
      assert html =~ "default"
      assert html =~ "sunken"
    end

    test "multiple blocks can be expanded simultaneously", %{conn: conn} do
      {:ok, view, _html} = live(conn, ~p"/admin/pages/home")

      page = Pages.get_page("home")
      hero = Enum.at(page.blocks, 0)
      featured = Enum.find(page.blocks, &(&1["type"] == "featured_products"))

      render_click(view, "toggle_expand", %{"id" => hero["id"]})
      render_click(view, "toggle_expand", %{"id" => featured["id"]})

      assert has_element?(view, "#block-settings-#{hero["id"]}")
      assert has_element?(view, "#block-settings-#{featured["id"]}")
    end

    test "expanded card has expanded class", %{conn: conn} do
      {:ok, view, _html} = live(conn, ~p"/admin/pages/home")

      page = Pages.get_page("home")
      hero = Enum.at(page.blocks, 0)

      refute has_element?(view, "#block-#{hero["id"]}.block-card-expanded")

      render_click(view, "toggle_expand", %{"id" => hero["id"]})

      assert has_element?(view, "#block-#{hero["id"]}.block-card-expanded")
    end
  end

  describe "repeater fields" do
    setup %{conn: conn, user: user} do
      %{conn: log_in_user(conn, user)}
    end

    test "repeater items render with input fields", %{conn: conn} do
      {:ok, view, _html} = live(conn, ~p"/admin/pages/contact")

      page = Pages.get_page("contact")
      info_card = Enum.find(page.blocks, &(&1["type"] == "info_card"))

      render_click(view, "toggle_expand", %{"id" => info_card["id"]})

      # Should render 3 default items with label/value inputs
      html = render(view)
      assert html =~ "Printing"
      assert html =~ "Delivery"
      assert html =~ "Issues"
    end

    test "editing a repeater item field sets dirty flag", %{conn: conn} do
      {:ok, view, _html} = live(conn, ~p"/admin/pages/contact")

      page = Pages.get_page("contact")
      info_card = Enum.find(page.blocks, &(&1["type"] == "info_card"))

      render_click(view, "toggle_expand", %{"id" => info_card["id"]})

      render_change(view, "update_block_settings", %{
        "block_id" => info_card["id"],
        "block_settings" => %{
          "title" => "Handy to know",
          "items" => %{
            "0" => %{"label" => "Shipping", "value" => "1-3 business days"},
            "1" => %{
              "label" => "Delivery",
              "value" => "Example: 3-7 business days after printing"
            },
            "2" => %{"label" => "Issues", "value" => "Example: Reprints for any defects"}
          }
        }
      })

      assert has_element?(view, ".admin-badge-warning", "Unsaved changes")
    end

    test "adding a repeater item appends an empty item", %{conn: conn} do
      {:ok, view, _html} = live(conn, ~p"/admin/pages/contact")

      page = Pages.get_page("contact")
      info_card = Enum.find(page.blocks, &(&1["type"] == "info_card"))

      render_click(view, "toggle_expand", %{"id" => info_card["id"]})

      # Should have 3 items initially
      assert render(view) |> count_repeater_items() == 3

      render_click(view, "repeater_add", %{
        "block-id" => info_card["id"],
        "field" => "items"
      })

      # Now 4 items
      assert render(view) |> count_repeater_items() == 4
      assert has_element?(view, ".admin-badge-warning", "Unsaved changes")
    end

    test "removing a repeater item removes it from the list", %{conn: conn} do
      {:ok, view, _html} = live(conn, ~p"/admin/pages/contact")

      page = Pages.get_page("contact")
      info_card = Enum.find(page.blocks, &(&1["type"] == "info_card"))

      render_click(view, "toggle_expand", %{"id" => info_card["id"]})

      render_click(view, "repeater_remove", %{
        "block-id" => info_card["id"],
        "field" => "items",
        "index" => "0"
      })

      html = render(view)
      assert count_repeater_items(html) == 2
      # "Printing" was item 0, should be gone
      refute html =~ "Printing"
      assert html =~ "Delivery"
    end

    test "moving a repeater item changes order", %{conn: conn} do
      {:ok, view, _html} = live(conn, ~p"/admin/pages/contact")

      page = Pages.get_page("contact")
      info_card = Enum.find(page.blocks, &(&1["type"] == "info_card"))

      render_click(view, "toggle_expand", %{"id" => info_card["id"]})

      render_click(view, "repeater_move", %{
        "block-id" => info_card["id"],
        "field" => "items",
        "index" => "0",
        "dir" => "down"
      })

      # Save and check the persisted order
      render_click(view, "save")

      saved = Pages.get_page("contact")
      saved_info = Enum.find(saved.blocks, &(&1["type"] == "info_card"))
      labels = Enum.map(saved_info["settings"]["items"], & &1["label"])

      # "Printing" moved from 0 to 1
      assert labels == ["Delivery", "Printing", "Issues"]
    end

    test "repeater changes persist after save", %{conn: conn} do
      {:ok, view, _html} = live(conn, ~p"/admin/pages/contact")

      page = Pages.get_page("contact")
      info_card = Enum.find(page.blocks, &(&1["type"] == "info_card"))

      render_click(view, "toggle_expand", %{"id" => info_card["id"]})

      # Edit item via phx-change
      render_change(view, "update_block_settings", %{
        "block_id" => info_card["id"],
        "block_settings" => %{
          "title" => "Good to know",
          "items" => %{
            "0" => %{"label" => "Shipping", "value" => "Fast shipping"},
            "1" => %{"label" => "Returns", "value" => "Easy returns"}
          }
        }
      })

      render_click(view, "save")

      saved = Pages.get_page("contact")
      saved_info = Enum.find(saved.blocks, &(&1["type"] == "info_card"))
      assert saved_info["settings"]["title"] == "Good to know"
      assert length(saved_info["settings"]["items"]) == 2
      assert Enum.at(saved_info["settings"]["items"], 0)["label"] == "Shipping"
      assert Enum.at(saved_info["settings"]["items"], 0)["value"] == "Fast shipping"
    end
  end

  describe "live preview" do
    setup %{conn: conn, user: user} do
      %{conn: log_in_user(conn, user)}
    end

    test "preview pane renders page content", %{conn: conn} do
      {:ok, _view, html} = live(conn, ~p"/admin/pages/home")

      # Preview pane should be in the DOM with the themed class
      assert html =~ "page-editor-preview themed"
      # Should render the page via PageRenderer (hero block is on home)
      assert html =~ "page-editor-preview-pane"
    end

    test "toggle preview switches between edit and preview on mobile", %{conn: conn} do
      {:ok, view, _html} = live(conn, ~p"/admin/pages/home")

      # Initially: editor visible, preview hidden on mobile
      assert has_element?(view, ".page-editor-pane:not(.page-editor-pane-hidden-mobile)")
      assert has_element?(view, ".page-editor-preview-hidden-mobile")

      # Toggle to preview
      render_click(view, "toggle_preview")

      assert has_element?(view, ".page-editor-pane-hidden-mobile")

      assert has_element?(
               view,
               ".page-editor-preview-pane:not(.page-editor-preview-hidden-mobile)"
             )

      # Toggle back to edit
      render_click(view, "toggle_preview")

      assert has_element?(view, ".page-editor-pane:not(.page-editor-pane-hidden-mobile)")
      assert has_element?(view, ".page-editor-preview-hidden-mobile")
    end

    test "preview updates when block settings change", %{conn: conn} do
      {:ok, view, _html} = live(conn, ~p"/admin/pages/home")

      page = Pages.get_page("home")
      hero = Enum.at(page.blocks, 0)

      render_click(view, "toggle_expand", %{"id" => hero["id"]})

      render_change(view, "update_block_settings", %{
        "block_id" => hero["id"],
        "block_settings" => %{"title" => "Preview test title"}
      })

      # The preview should show the updated title
      html = render(view)
      assert html =~ "Preview test title"
    end

    test "preview updates after block reorder", %{conn: conn} do
      {:ok, view, _html} = live(conn, ~p"/admin/pages/home")

      page = Pages.get_page("home")
      first_block = Enum.at(page.blocks, 0)

      render_click(view, "move_down", %{"id" => first_block["id"]})

      # Should still render without errors
      html = render(view)
      assert html =~ "page-editor-preview themed"
    end

    test "preview toggle button shows in header", %{conn: conn} do
      {:ok, view, _html} = live(conn, ~p"/admin/pages/home")

      # Toggle button should be present
      assert has_element?(view, ".page-editor-toggle-preview")
    end
  end

  describe "custom pages on index" do
    setup %{conn: conn, user: user} do
      %{conn: log_in_user(conn, user)}
    end

    test "shows new page button", %{conn: conn} do
      {:ok, view, _html} = live(conn, ~p"/admin/pages")
      assert has_element?(view, "a[href='/admin/pages/new']", "New page")
    end

    test "shows custom pages section when pages exist", %{conn: conn} do
      {:ok, _} = Pages.create_custom_page(%{slug: "faq", title: "FAQ"})
      {:ok, view, _html} = live(conn, ~p"/admin/pages")

      assert has_element?(view, ".page-group-title", "Custom pages")
      assert has_element?(view, ".page-card-title", "FAQ")
    end

    test "does not show custom pages section when empty", %{conn: conn} do
      {:ok, view, _html} = live(conn, ~p"/admin/pages")
      refute has_element?(view, ".page-group-title", "Custom pages")
    end

    test "shows draft badge for unpublished pages", %{conn: conn} do
      {:ok, _} =
        Pages.create_custom_page(%{slug: "draft-page", title: "Draft", published: false})

      {:ok, view, _html} = live(conn, ~p"/admin/pages")
      assert has_element?(view, ".admin-badge-warning", "Draft")
    end

    test "custom page card links to editor", %{conn: conn} do
      {:ok, _} = Pages.create_custom_page(%{slug: "faq", title: "FAQ"})
      {:ok, view, _html} = live(conn, ~p"/admin/pages")

      assert has_element?(view, "a[href='/admin/pages/faq']")
    end

    test "shows slug in card meta", %{conn: conn} do
      {:ok, _} = Pages.create_custom_page(%{slug: "our-story", title: "Our story"})
      {:ok, view, _html} = live(conn, ~p"/admin/pages")

      assert has_element?(view, ".page-card-meta", "/our-story")
    end

    test "delete removes page from list", %{conn: conn} do
      {:ok, _} = Pages.create_custom_page(%{slug: "faq", title: "FAQ"})
      {:ok, view, _html} = live(conn, ~p"/admin/pages")

      assert has_element?(view, ".page-card-title", "FAQ")

      view
      |> element("button[phx-click='delete_custom_page'][phx-value-slug='faq']")
      |> render_click()

      refute has_element?(view, ".page-card-title", "FAQ")
      assert render(view) =~ "Page deleted"
    end
  end

  describe "custom page creation" do
    setup %{conn: conn, user: user} do
      %{conn: log_in_user(conn, user)}
    end

    test "renders creation form", %{conn: conn} do
      {:ok, view, _html} = live(conn, ~p"/admin/pages/new")

      assert has_element?(view, "h1", "New page")
      assert has_element?(view, "#custom-page-form")
    end

    test "creating with valid data redirects to editor", %{conn: conn} do
      {:ok, view, _html} = live(conn, ~p"/admin/pages/new")

      view
      |> form("#custom-page-form", page: %{title: "FAQ", slug: "faq"})
      |> render_submit()

      assert_redirect(view, ~p"/admin/pages/faq")
    end

    test "creating with empty title shows error", %{conn: conn} do
      {:ok, view, _html} = live(conn, ~p"/admin/pages/new")

      view
      |> form("#custom-page-form", page: %{title: "", slug: "faq"})
      |> render_submit()

      assert has_element?(view, "#custom-page-form")
    end

    test "creating with reserved slug shows error", %{conn: conn} do
      {:ok, view, _html} = live(conn, ~p"/admin/pages/new")

      html =
        view
        |> form("#custom-page-form", page: %{title: "Admin", slug: "admin"})
        |> render_submit()

      assert html =~ "is reserved"
    end

    test "creating with duplicate slug shows error", %{conn: conn} do
      {:ok, _} = Pages.create_custom_page(%{slug: "faq", title: "FAQ"})

      {:ok, view, _html} = live(conn, ~p"/admin/pages/new")

      html =
        view
        |> form("#custom-page-form", page: %{title: "FAQ 2", slug: "faq"})
        |> render_submit()

      assert html =~ "has already been taken"
    end

    test "auto-slugifies title during validation", %{conn: conn} do
      {:ok, view, _html} = live(conn, ~p"/admin/pages/new")

      html =
        view
        |> form("#custom-page-form", page: %{title: "Our Story"})
        |> render_change()

      assert html =~ ~s(value="our-story")
    end
  end

  describe "custom page settings" do
    setup %{conn: conn, user: user} do
      {:ok, _} = Pages.create_custom_page(%{slug: "help-page", title: "Help"})
      %{conn: log_in_user(conn, user)}
    end

    test "renders settings form", %{conn: conn} do
      {:ok, view, _html} = live(conn, ~p"/admin/pages/help-page/settings")

      assert has_element?(view, "h1", "Page settings")
      assert has_element?(view, "#custom-page-form")
    end

    test "updating title saves correctly", %{conn: conn} do
      {:ok, view, _html} = live(conn, ~p"/admin/pages/help-page/settings")

      view
      |> form("#custom-page-form", page: %{title: "Help centre"})
      |> render_submit()

      assert_redirect(view, ~p"/admin/pages/help-page")

      page = Pages.get_page("help-page")
      assert page.title == "Help centre"
    end

    test "updating slug redirects to new editor path", %{conn: conn} do
      {:ok, view, _html} = live(conn, ~p"/admin/pages/help-page/settings")

      view
      |> form("#custom-page-form", page: %{slug: "support"})
      |> render_submit()

      assert_redirect(view, ~p"/admin/pages/support")
    end

    test "settings for nonexistent page redirects", %{conn: conn} do
      assert {:error, {:live_redirect, %{to: "/admin/pages"}}} =
               live(conn, ~p"/admin/pages/nonexistent/settings")
    end
  end

  describe "editor for custom pages" do
    setup %{conn: conn, user: user} do
      {:ok, _} = Pages.create_custom_page(%{slug: "size-guide", title: "Size guide"})
      %{conn: log_in_user(conn, user)}
    end

    test "shows settings button for custom pages", %{conn: conn} do
      {:ok, view, _html} = live(conn, ~p"/admin/pages/size-guide")

      assert has_element?(view, "button", "Settings")
    end

    test "does not show reset to defaults for custom pages", %{conn: conn} do
      {:ok, view, _html} = live(conn, ~p"/admin/pages/size-guide")

      refute has_element?(view, "button", "Reset to defaults")
    end

    test "shows reset to defaults for system pages", %{conn: conn} do
      {:ok, view, _html} = live(conn, ~p"/admin/pages/home")

      assert has_element?(view, "button", "Reset to defaults")
      refute has_element?(view, "a[href='/admin/pages/home/settings']")
    end
  end

  describe "legal page editor" do
    setup %{conn: conn, user: user} do
      %{conn: log_in_user(conn, user)}
    end

    test "shows regenerate button for privacy page", %{conn: conn} do
      {:ok, view, _html} = live(conn, ~p"/admin/pages/privacy")

      assert has_element?(view, "button[phx-click='regenerate_legal']", "Regenerate")
    end

    test "shows regenerate button for delivery page", %{conn: conn} do
      {:ok, view, _html} = live(conn, ~p"/admin/pages/delivery")

      assert has_element?(view, "button[phx-click='regenerate_legal']", "Regenerate")
    end

    test "does not show regenerate button for home page", %{conn: conn} do
      {:ok, view, _html} = live(conn, ~p"/admin/pages/home")

      refute has_element?(view, "button[phx-click='regenerate_legal']")
    end

    test "shows auto-generated badge for legal pages on mount", %{conn: conn} do
      {:ok, view, _html} = live(conn, ~p"/admin/pages/privacy")

      assert has_element?(view, ".admin-badge-info", "Auto-generated from settings")
    end

    test "auto-populates content_body on mount for legal pages", %{conn: conn} do
      {:ok, view, _html} = live(conn, ~p"/admin/pages/privacy")

      # The content_body block should be expanded to see the content
      page = Pages.get_page("privacy")
      content_body = Enum.find(page.blocks, &(&1["type"] == "content_body"))
      render_click(view, "toggle_expand", %{"id" => content_body["id"]})

      html = render(view)
      # Should contain generated legal content
      assert html =~ "What we collect"
    end

    test "shows customised badge after manual edit", %{conn: conn} do
      {:ok, view, _html} = live(conn, ~p"/admin/pages/privacy")

      page = Pages.get_page("privacy")
      content_body = Enum.find(page.blocks, &(&1["type"] == "content_body"))

      render_click(view, "toggle_expand", %{"id" => content_body["id"]})

      render_change(view, "update_block_settings", %{
        "block_id" => content_body["id"],
        "block_settings" => %{"content" => "Custom privacy content here"}
      })

      assert has_element?(view, ".admin-badge", "Customised")
      refute has_element?(view, ".admin-badge-info", "Auto-generated from settings")
    end
  end

  defp count_repeater_items(html) do
    Regex.scan(~r/class="repeater-item"/, html) |> length()
  end
end
