defmodule ToweropsWeb.Admin.AuditLive.IndexTest do
  use ToweropsWeb.ConnCase, async: true

  import Phoenix.LiveViewTest

  alias Towerops.Admin

  setup do
    user = Towerops.AccountsFixtures.user_fixture()
    user = user |> Ecto.Changeset.change(%{is_superuser: true}) |> Towerops.Repo.update!()
    {:ok, organization} = Towerops.Organizations.create_organization(%{name: "Test Org"}, user.id)

    token = Towerops.Accounts.generate_user_session_token(user)

    conn =
      build_conn()
      |> Phoenix.ConnTest.init_test_session(%{})
      |> Plug.Conn.put_session(:user_token, token)

    %{conn: conn, user: user, organization: organization}
  end

  describe "mount" do
    test "renders audit log page for superuser", %{conn: conn} do
      {:ok, _view, html} = live(conn, ~p"/admin/audit")

      assert html =~ "Audit Logs"
    end

    test "redirects non-superuser to /orgs" do
      regular_user = Towerops.AccountsFixtures.user_fixture()
      token = Towerops.Accounts.generate_user_session_token(regular_user)

      conn =
        build_conn()
        |> Phoenix.ConnTest.init_test_session(%{})
        |> Plug.Conn.put_session(:user_token, token)

      assert {:error, {:redirect, %{to: "/orgs"}}} = live(conn, ~p"/admin/audit")
    end

    test "shows empty state when no audit logs exist", %{conn: conn} do
      {:ok, _view, html} = live(conn, ~p"/admin/audit")

      assert html =~ "No audit logs found"
    end

    test "displays audit logs when they exist", %{conn: conn, user: user} do
      {:ok, _log} =
        Admin.create_audit_log(%{
          action: "impersonate_start",
          superuser_id: user.id
        })

      {:ok, _view, html} = live(conn, ~p"/admin/audit")

      assert html =~ "Impersonate start"
      assert html =~ user.email
    end
  end

  describe "search" do
    setup %{user: user} do
      target_user = Towerops.AccountsFixtures.user_fixture()

      {:ok, _log1} =
        Admin.create_audit_log(%{
          action: "impersonate_start",
          superuser_id: user.id,
          target_user_id: target_user.id
        })

      {:ok, _log2} =
        Admin.create_audit_log(%{
          action: "user_delete",
          superuser_id: user.id,
          metadata: %{email: "deleted@example.com"}
        })

      %{target_user: target_user}
    end

    test "filters audit logs by action", %{conn: conn} do
      {:ok, view, _html} = live(conn, ~p"/admin/audit")

      html =
        view
        |> form("form[phx-submit=search]", %{"action" => "impersonate_start"})
        |> render_submit()

      assert html =~ "Impersonate start"
      # The action dropdown always contains "User delete" as an option,
      # so check the table body specifically for absence of the log entry
      refute has_element?(view, "td span", "User delete")
    end

    test "filters audit logs by email", %{conn: conn, user: user} do
      {:ok, view, _html} = live(conn, ~p"/admin/audit")

      html =
        view
        |> form("form[phx-submit=search]", %{"email" => user.email})
        |> render_submit()

      assert html =~ user.email
    end
  end

  describe "clear_filters" do
    test "resets all search filters", %{conn: conn, user: user} do
      {:ok, _log} =
        Admin.create_audit_log(%{
          action: "impersonate_start",
          superuser_id: user.id
        })

      {:ok, _log2} =
        Admin.create_audit_log(%{
          action: "user_delete",
          superuser_id: user.id
        })

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

      # First, apply a filter
      view
      |> form("form[phx-submit=search]", %{"action" => "impersonate_start"})
      |> render_submit()

      # Then clear filters
      html = render_click(view, "clear_filters")

      # Both logs should be visible again
      assert html =~ "Impersonate start"
      assert html =~ "User delete"
    end
  end

  describe "pagination" do
    test "navigates to next page", %{conn: conn, user: user} do
      # Create more than 50 audit logs (the per_page default)
      for _i <- 1..51 do
        {:ok, _log} =
          Admin.create_audit_log(%{
            action: "device_created",
            superuser_id: user.id
          })
      end

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

      assert html =~ "Page 1"

      html = render_click(view, "next_page")

      assert html =~ "Page 2"
    end

    test "navigates to previous page", %{conn: conn, user: user} do
      for _i <- 1..51 do
        {:ok, _log} =
          Admin.create_audit_log(%{
            action: "device_created",
            superuser_id: user.id
          })
      end

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

      render_click(view, "next_page")
      html = render_click(view, "prev_page")

      assert html =~ "Page 1"
    end

    test "does not go below page 1", %{conn: conn, user: user} do
      # Need at least one log so the pagination UI renders
      {:ok, _log} =
        Admin.create_audit_log(%{
          action: "device_created",
          superuser_id: user.id
        })

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

      html = render_click(view, "prev_page")

      assert html =~ "Page 1"
    end
  end
end
