defmodule ToweropsWeb.AgentLive.EditTest do
  use ToweropsWeb.ConnCase

  import Phoenix.LiveViewTest

  alias Towerops.AgentsFixtures

  setup %{conn: conn} do
    user = Towerops.AccountsFixtures.user_fixture()
    {:ok, organization} = Towerops.Organizations.create_organization(%{name: "Test Org"}, user.id)

    conn =
      conn
      |> log_in_user(user)
      |> put_session(:current_organization_id, organization.id)

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

  defp create_agent(organization_id, name \\ nil) do
    {:ok, agent_token, _raw_token} = AgentsFixtures.agent_token_fixture(organization_id, name)
    agent_token
  end

  describe "mount and display" do
    test "renders edit form with agent name", %{conn: conn, organization: org} do
      agent = create_agent(org.id, "Original Agent Name")

      {:ok, _view, html} = live(conn, ~p"/agents/#{agent.id}/edit")

      assert html =~ "Edit Agent"
      assert html =~ "Original Agent Name"
      assert html =~ "Agent Name"
      assert html =~ "Save Changes"
      assert html =~ "Cancel"
    end

    test "displays allow remote debug checkbox", %{conn: conn, organization: org} do
      agent = create_agent(org.id)

      {:ok, _view, html} = live(conn, ~p"/agents/#{agent.id}/edit")

      assert html =~ "Allow Remote Debugging"
    end

    test "displays back to agent link", %{conn: conn, organization: org} do
      agent = create_agent(org.id)

      {:ok, _view, html} = live(conn, ~p"/agents/#{agent.id}/edit")

      assert html =~ "Back to agent"
      assert html =~ ~p"/agents/#{agent.id}"
    end

    test "sets page title to Edit plus agent name", %{conn: conn, organization: org} do
      agent = create_agent(org.id, "My Agent")

      {:ok, _view, html} = live(conn, ~p"/agents/#{agent.id}/edit")

      assert html =~ "Edit My Agent"
    end
  end

  describe "form validation" do
    test "validates name changes in real time", %{conn: conn, organization: org} do
      agent = create_agent(org.id, "Original Name")

      {:ok, view, _html} = live(conn, ~p"/agents/#{agent.id}/edit")

      # Submit empty name to trigger validation error
      html =
        view
        |> form("#edit-agent-form", agent_token: %{name: ""})
        |> render_change()

      assert html =~ "can&#39;t be blank" || html =~ "can't be blank"
    end

    test "validates with valid name", %{conn: conn, organization: org} do
      agent = create_agent(org.id, "Original Name")

      {:ok, view, _html} = live(conn, ~p"/agents/#{agent.id}/edit")

      html =
        view
        |> form("#edit-agent-form", agent_token: %{name: "Updated Agent Name"})
        |> render_change()

      refute html =~ "can&#39;t be blank"
      refute html =~ "can't be blank"
    end
  end

  describe "form submission" do
    test "saves changes and redirects to show page", %{conn: conn, organization: org} do
      agent = create_agent(org.id, "Original Name")

      {:ok, view, _html} = live(conn, ~p"/agents/#{agent.id}/edit")

      view
      |> form("#edit-agent-form", agent_token: %{name: "Updated Agent Name"})
      |> render_submit()

      flash = assert_redirect(view, ~p"/agents/#{agent.id}")

      assert flash["info"] =~ "Agent updated successfully"
    end

    test "shows error when saving with blank name", %{conn: conn, organization: org} do
      agent = create_agent(org.id, "Original Name")

      {:ok, view, _html} = live(conn, ~p"/agents/#{agent.id}/edit")

      html =
        view
        |> form("#edit-agent-form", agent_token: %{name: ""})
        |> render_submit()

      assert html =~ "can&#39;t be blank" || html =~ "can't be blank"
    end
  end

  describe "authentication" do
    test "redirects to login when not authenticated" do
      conn = build_conn()

      assert {:error, {:redirect, %{to: to}}} =
               live(conn, ~p"/agents/#{Ecto.UUID.generate()}/edit")

      assert to =~ "/users/log-in"
    end
  end

  describe "authorization" do
    test "raises when editing agent from another organization", %{conn: conn} do
      other_user = Towerops.AccountsFixtures.user_fixture()
      {:ok, other_org} = Towerops.Organizations.create_organization(%{name: "Other Org"}, other_user.id)
      other_agent = create_agent(other_org.id, "Other Org Agent")

      assert_raise Ecto.NoResultsError, fn ->
        live(conn, ~p"/agents/#{other_agent.id}/edit")
      end
    end

    test "superuser can edit agent from any organization" do
      superuser = Towerops.AccountsFixtures.user_fixture()

      superuser
      |> Ecto.Changeset.change(%{is_superuser: true})
      |> Towerops.Repo.update!()

      {:ok, super_org} = Towerops.Organizations.create_organization(%{name: "Super Org"}, superuser.id)

      other_user = Towerops.AccountsFixtures.user_fixture()
      {:ok, other_org} = Towerops.Organizations.create_organization(%{name: "Other Org"}, other_user.id)
      other_agent = create_agent(other_org.id, "Cross-Org Agent")

      super_conn =
        build_conn()
        |> log_in_user(superuser)
        |> put_session(:current_organization_id, super_org.id)

      {:ok, _view, html} = live(super_conn, ~p"/agents/#{other_agent.id}/edit")

      assert html =~ "Cross-Org Agent"
    end
  end
end
