defmodule MvWeb.CustomFieldLive.DeletionTest do
  @moduledoc """
  Tests for CustomFieldLive.IndexComponent deletion modal and slug confirmation.
  Tests the custom field management component embedded in the settings page.

  Tests cover:
  - Opening deletion confirmation modal
  - Displaying correct member count
  - Slug confirmation input
  - Successful deletion with correct slug
  - Failed deletion with incorrect slug
  - Canceling deletion
  - Button states (enabled/disabled based on slug match)
  """
  use MvWeb.ConnCase, async: true

  import Phoenix.LiveViewTest
  require Ash.Query

  alias Mv.Membership.{CustomField, CustomFieldValue, Member}

  setup do
    system_actor = Mv.Helpers.SystemActor.get_system_actor()
    admin_role = Mv.Fixtures.role_fixture("admin")

    # Create admin user for testing (must have admin role to read/manage CustomField)
    {:ok, user} =
      Mv.Accounts.User
      |> Ash.Changeset.for_create(:register_with_password, %{
        email: "admin#{System.unique_integer([:positive])}@mv.local",
        password: "testpassword123"
      })
      |> Ash.create(actor: system_actor)

    {:ok, user} =
      user
      |> Ash.Changeset.for_update(:update, %{})
      |> Ash.Changeset.manage_relationship(:role, admin_role, type: :append_and_remove)
      |> Ash.update(actor: system_actor)

    user_with_role = Ash.load!(user, :role, domain: Mv.Accounts, actor: system_actor)
    conn = log_in_user(build_conn(), user_with_role)
    # Use English locale so "Delete" link text matches in assertions
    session = conn.private[:plug_session] || %{}
    conn = Plug.Test.init_test_session(conn, Map.put(session, "locale", "en"))
    %{conn: conn, user: user_with_role}
  end

  describe "delete button and modal" do
    test "opens modal with correct member count when delete is clicked", %{conn: conn} do
      {:ok, member} = create_member()
      {:ok, custom_field} = create_custom_field("test_field", :string)

      # Create custom field value
      create_custom_field_value(member, custom_field, "test")

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

      # Click delete button - find the delete link within the component
      view
      |> element("#custom-fields-component a", "Delete")
      |> render_click()

      # Modal should be visible
      assert has_element?(view, "#delete-custom-field-modal")

      # Should show correct member count (1 member)
      assert render(view) =~ "1 member has a value assigned for this custom field"

      # Should show the slug
      assert render(view) =~ custom_field.slug
    end

    test "shows correct plural form for multiple members", %{conn: conn} do
      {:ok, member1} = create_member()
      {:ok, member2} = create_member()
      {:ok, custom_field} = create_custom_field("test_field", :string)

      # Create values for both members
      create_custom_field_value(member1, custom_field, "test1")
      create_custom_field_value(member2, custom_field, "test2")

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

      view
      |> element("#custom-fields-component a", "Delete")
      |> render_click()

      # Should show plural form
      assert render(view) =~ "2 members have values assigned for this custom field"
    end

    test "shows 0 members for custom field without values", %{conn: conn} do
      {:ok, _custom_field} = create_custom_field("test_field", :string)

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

      view
      |> element("#custom-fields-component a", "Delete")
      |> render_click()

      # Should show 0 members
      assert render(view) =~ "0 members have values assigned for this custom field"
    end
  end

  describe "slug confirmation input" do
    test "updates confirmation state when typing", %{conn: conn} do
      {:ok, custom_field} = create_custom_field("test_field", :string)

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

      view
      |> element("#custom-fields-component a", "Delete")
      |> render_click()

      # Type in slug input - use element to find the form with phx-target
      view
      |> element("#delete-custom-field-modal form")
      |> render_change(%{"slug" => custom_field.slug})

      # Confirm button should be enabled now (no disabled attribute on the confirm button)
      refute has_element?(view, "#delete-custom-field-modal button.btn-error[disabled]")
    end

    test "delete button is disabled when slug doesn't match", %{conn: conn} do
      {:ok, _custom_field} = create_custom_field("test_field", :string)

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

      view
      |> element("#custom-fields-component a", "Delete")
      |> render_click()

      # Type wrong slug - use element to find the form with phx-target
      view
      |> element("#delete-custom-field-modal form")
      |> render_change(%{"slug" => "wrong-slug"})

      # Confirm button should be disabled
      assert has_element?(view, "#delete-custom-field-modal button.btn-error[disabled]")
    end
  end

  describe "confirm deletion" do
    test "successfully deletes custom field with correct slug", %{conn: conn} do
      {:ok, member} = create_member()
      {:ok, custom_field} = create_custom_field("test_field", :string)
      {:ok, custom_field_value} = create_custom_field_value(member, custom_field, "test")

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

      # Open modal
      view
      |> element("#custom-fields-component a", "Delete")
      |> render_click()

      # Enter correct slug - use element to find the form with phx-target
      view
      |> element("#delete-custom-field-modal form")
      |> render_change(%{"slug" => custom_field.slug})

      # Click confirm
      view
      |> element("#delete-custom-field-modal button", "Delete Custom Field and All Values")
      |> render_click()

      # Should show success message
      assert render(view) =~ "Data field deleted successfully"

      system_actor = Mv.Helpers.SystemActor.get_system_actor()

      # Custom field should be gone from database
      assert {:error, _} = Ash.get(CustomField, custom_field.id, actor: system_actor)

      # Custom field value should also be gone (CASCADE)
      assert {:error, _} = Ash.get(CustomFieldValue, custom_field_value.id, actor: system_actor)

      # Member should still exist
      assert {:ok, _} = Ash.get(Member, member.id, actor: system_actor)
    end

    test "button remains disabled and custom field not deleted when slug doesn't match", %{
      conn: conn
    } do
      {:ok, custom_field} = create_custom_field("test_field", :string)

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

      view
      |> element("#custom-fields-component a", "Delete")
      |> render_click()

      # Enter wrong slug - use element to find the form with phx-target
      view
      |> element("#delete-custom-field-modal form")
      |> render_change(%{"slug" => "wrong-slug"})

      # Confirm button should be disabled and we cannot click it
      assert has_element?(view, "#delete-custom-field-modal button.btn-error[disabled]")

      # Custom field should still exist since deletion couldn't proceed
      system_actor = Mv.Helpers.SystemActor.get_system_actor()
      assert {:ok, _} = Ash.get(CustomField, custom_field.id, actor: system_actor)
    end
  end

  describe "cancel deletion" do
    test "closes modal without deleting", %{conn: conn} do
      {:ok, custom_field} = create_custom_field("test_field", :string)

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

      view
      |> element("#custom-fields-component a", "Delete")
      |> render_click()

      # Modal should be visible
      assert has_element?(view, "#delete-custom-field-modal")

      # Click cancel
      view
      |> element("#delete-custom-field-modal button", "Cancel")
      |> render_click()

      # Modal should be gone
      refute has_element?(view, "#delete-custom-field-modal")

      # Custom field should still exist
      system_actor = Mv.Helpers.SystemActor.get_system_actor()
      assert {:ok, _} = Ash.get(CustomField, custom_field.id, actor: system_actor)
    end
  end

  describe "create custom field" do
    test "submitting new data field form creates custom field and shows success", %{conn: conn} do
      {:ok, view, _html} = live(conn, ~p"/settings")

      # Open "New Data Field" form
      view
      |> element("#custom-fields-component button", "New Data Field")
      |> render_click()

      # Form is visible; submit with valid data
      form_params = %{
        "custom_field" => %{
          "name" => "Created via Form",
          "value_type" => "string",
          "description" => "",
          "required" => "false",
          "show_in_overview" => "true"
        }
      }

      view
      |> form("#custom-field-form-new-form", form_params)
      |> render_submit()

      # Success flash (FormComponent needs actor from parent; without it KeyError would occur)
      assert render(view) =~ "successfully"

      # Custom field was created in DB
      system_actor = Mv.Helpers.SystemActor.get_system_actor()
      search_name = "Created via Form"

      [custom_field] =
        Mv.Membership.CustomField
        |> Ash.Query.filter(name == ^search_name)
        |> Ash.read!(actor: system_actor)

      assert custom_field.value_type == :string
    end
  end

  # Helper functions (use code interface so actor is in validation context)
  defp create_member do
    system_actor = Mv.Helpers.SystemActor.get_system_actor()

    Mv.Membership.create_member(
      %{
        first_name: "Test",
        last_name: "User#{System.unique_integer([:positive])}",
        email: "test#{System.unique_integer([:positive])}@example.com"
      },
      actor: system_actor
    )
  end

  defp create_custom_field(name, value_type) do
    system_actor = Mv.Helpers.SystemActor.get_system_actor()

    CustomField
    |> Ash.Changeset.for_create(:create, %{
      name: "#{name}_#{System.unique_integer([:positive])}",
      value_type: value_type
    })
    |> Ash.create(actor: system_actor)
  end

  defp create_custom_field_value(member, custom_field, value) do
    system_actor = Mv.Helpers.SystemActor.get_system_actor()

    CustomFieldValue
    |> Ash.Changeset.for_create(:create, %{
      member_id: member.id,
      custom_field_id: custom_field.id,
      value: %{"_union_type" => "string", "_union_value" => value}
    })
    |> Ash.create(actor: system_actor)
  end

  defp log_in_user(conn, user) do
    conn
    |> Phoenix.ConnTest.init_test_session(%{})
    |> AshAuthentication.Plug.Helpers.store_in_session(user)
  end
end
