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

  import Phoenix.LiveViewTest
  import Berrypod.AccountsFixtures

  alias Berrypod.{Pages, Settings}
  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/navigation")
      assert {:redirect, %{to: path}} = redirect
      assert path == ~p"/users/log-in"
    end
  end

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

    test "renders with header and footer sections", %{conn: conn} do
      {:ok, _view, html} = live(conn, ~p"/admin/navigation")

      assert html =~ "Navigation"
      assert html =~ "Header navigation"
      assert html =~ "Footer navigation"
    end

    test "shows default header items", %{conn: conn} do
      {:ok, _view, html} = live(conn, ~p"/admin/navigation")

      assert html =~ "Home"
      assert html =~ "Shop"
      assert html =~ "About"
      assert html =~ "Contact"
    end

    test "shows default footer items", %{conn: conn} do
      {:ok, _view, html} = live(conn, ~p"/admin/navigation")

      assert html =~ "Delivery &amp; returns"
      assert html =~ "Privacy policy"
      assert html =~ "Terms of service"
    end

    test "adding an item appends to list", %{conn: conn} do
      {:ok, view, _html} = live(conn, ~p"/admin/navigation")

      render_click(view, "add_item", %{"section" => "header"})

      # Should have 5 items now (4 defaults + 1 new)
      html = render(view)
      # New empty item has empty placeholder inputs
      assert Regex.scan(~r/phx-value-section="header".*?phx-value-field="label"/, html)
             |> length() == 5
    end

    test "removing an item removes from list", %{conn: conn} do
      {:ok, view, _html} = live(conn, ~p"/admin/navigation")

      render_click(view, "remove_item", %{"section" => "header", "index" => "0"})

      html = render(view)
      # "Home" should be gone (it was index 0)
      refute html =~ ~s(value="Home")
      # "Shop" should still be there
      assert html =~ ~s(value="Shop")
    end

    test "moving item up reorders", %{conn: conn} do
      {:ok, view, _html} = live(conn, ~p"/admin/navigation")

      render_click(view, "move_item", %{
        "section" => "header",
        "index" => "1",
        "dir" => "up"
      })

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

      items = Settings.get_setting("header_nav")
      assert Enum.at(items, 0)["label"] == "Shop"
      assert Enum.at(items, 1)["label"] == "Home"
    end

    test "adding a custom page creates nav item", %{conn: conn} do
      {:ok, _} = Pages.create_custom_page(%{slug: "faq", title: "FAQ"})

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

      render_click(view, "add_page", %{"section" => "header", "slug" => "faq"})

      html = render(view)
      assert html =~ ~s(value="FAQ")
      assert html =~ ~s(value="/faq")
    end

    test "save persists to settings", %{conn: conn} do
      {:ok, view, _html} = live(conn, ~p"/admin/navigation")

      render_click(view, "remove_item", %{"section" => "footer", "index" => "0"})
      render_click(view, "save")

      assert render(view) =~ "Navigation saved"

      items = Settings.get_setting("footer_nav")
      assert length(items) == 3
      assert Enum.at(items, 0)["label"] == "Privacy policy"
    end

    test "reset defaults restores original items", %{conn: conn} do
      # Save custom nav
      Settings.put_setting("header_nav", [%{"label" => "Only", "href" => "/only"}], "json")

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

      # Should show the custom item
      assert render(view) =~ ~s(value="Only")

      render_click(view, "reset_defaults")

      html = render(view)
      assert html =~ ~s(value="Home")
      assert html =~ ~s(value="Shop")
      refute html =~ ~s(value="Only")
    end

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

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

      render_click(view, "add_item", %{"section" => "header"})

      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/navigation")

      render_click(view, "add_item", %{"section" => "header"})
      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/navigation")

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