defmodule MvWeb.MemberLive.ShowTest do
  @moduledoc """
  Tests for the member show page.

  Tests cover:
  - Displaying member information
  - Custom Fields section visibility (Issue #282 regression test)
  - Custom field values formatting

  ## Note on async
  Tests can run with `async: true` because:
  - Each test explicitly manages its own custom fields (creates/deletes as needed)
  - The SQL Sandbox provides proper isolation between parallel tests
  - Custom field cleanup in tests ensures no interference between tests
  """
  use MvWeb.ConnCase, async: true
  import Phoenix.LiveViewTest
  require Ash.Query
  use Gettext, backend: MvWeb.Gettext

  alias Mv.Membership.{CustomField, CustomFieldValue}

  setup do
    system_actor = Mv.Helpers.SystemActor.get_system_actor()

    # Create test member
    {:ok, member} =
      Mv.Membership.create_member(
        %{first_name: "Alice", last_name: "Anderson", email: "alice@example.com"},
        actor: system_actor
      )

    %{member: member, actor: system_actor}
  end

  describe "custom fields section visibility (Issue #282)" do
    test "displays Custom Fields section even when member has no custom field values", %{
      conn: conn,
      member: member,
      actor: actor
    } do
      # Create a custom field but no value for the member
      {:ok, custom_field} =
        CustomField
        |> Ash.Changeset.for_create(:create, %{
          name: "phone_mobile",
          value_type: :string
        })
        |> Ash.create(actor: actor)

      conn = conn_with_oidc_user(conn)
      {:ok, _view, html} = live(conn, ~p"/members/#{member}")

      # Custom Fields section should be visible
      assert html =~ gettext("Custom Fields")

      # Custom field label should be visible
      assert html =~ custom_field.name

      # Value should show placeholder for empty value
      assert html =~ "—" or html =~ gettext("Not set")
    end

    test "displays Custom Fields section with multiple custom fields, some without values", %{
      conn: conn,
      member: member,
      actor: actor
    } do
      # Create multiple custom fields
      {:ok, field1} =
        CustomField
        |> Ash.Changeset.for_create(:create, %{
          name: "phone_mobile",
          value_type: :string
        })
        |> Ash.create(actor: actor)

      {:ok, field2} =
        CustomField
        |> Ash.Changeset.for_create(:create, %{
          name: "membership_number",
          value_type: :integer
        })
        |> Ash.create(actor: actor)

      # Create value only for first field
      {:ok, _cfv} =
        CustomFieldValue
        |> Ash.Changeset.for_create(:create, %{
          member_id: member.id,
          custom_field_id: field1.id,
          value: %{"_union_type" => "string", "_union_value" => "+49123456789"}
        })
        |> Ash.create(actor: actor)

      conn = conn_with_oidc_user(conn)
      {:ok, _view, html} = live(conn, ~p"/members/#{member}")

      # Custom Fields section should be visible
      assert html =~ gettext("Custom Fields")

      # Both field labels should be visible
      assert html =~ field1.name
      assert html =~ field2.name

      # First field should show value
      assert html =~ "+49123456789"

      # Second field should show placeholder
      assert html =~ "—" or html =~ gettext("Not set")
    end

    test "does not display Custom Fields section when no custom fields exist", %{
      conn: conn,
      member: member,
      actor: actor
    } do
      # Ensure no custom fields exist for this test
      # This ensures test isolation even if previous tests created custom fields
      existing_custom_fields = Ash.read!(CustomField, actor: actor)

      for cf <- existing_custom_fields do
        Ash.destroy!(cf, actor: actor)
      end

      # Verify no custom fields exist
      assert Ash.read!(CustomField, actor: actor) == []

      conn = conn_with_oidc_user(conn)
      {:ok, _view, html} = live(conn, ~p"/members/#{member}")

      # Custom Fields section should NOT be visible
      refute html =~ gettext("Additional Data Fields")
    end
  end

  describe "delete action" do
    test "renders Danger zone section and Delete button when user can destroy member", %{
      conn: conn,
      member: member
    } do
      conn = conn_with_oidc_user(conn)
      {:ok, view, html} = live(conn, ~p"/members/#{member}")

      assert has_element?(view, "[data-testid='member-delete']")
      assert html =~ gettext("Danger zone")
      assert has_element?(view, "section[aria-labelledby='danger-zone-heading']")
    end

    test "delete event removes member and redirects to index", %{
      conn: conn,
      member: member
    } do
      conn = conn_with_oidc_user(conn)
      {:ok, view, _html} = live(conn, ~p"/members/#{member}")

      view
      |> render_click("delete", %{"id" => member.id})

      assert_redirect(view, ~p"/members")

      refute Mv.Membership.Member
             |> Ash.Query.filter(id == ^member.id)
             |> Ash.exists?()
    end
  end

  describe "custom field value formatting" do
    test "formats string custom field values", %{conn: conn, member: member, actor: actor} do
      {:ok, custom_field} =
        CustomField
        |> Ash.Changeset.for_create(:create, %{
          name: "phone_mobile",
          value_type: :string
        })
        |> Ash.create(actor: actor)

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

      conn = conn_with_oidc_user(conn)
      {:ok, _view, html} = live(conn, ~p"/members/#{member}")

      assert html =~ "+49123456789"
    end

    test "formats email custom field values as mailto links", %{
      conn: conn,
      member: member,
      actor: actor
    } do
      {:ok, custom_field} =
        CustomField
        |> Ash.Changeset.for_create(:create, %{
          name: "private_email",
          value_type: :email
        })
        |> Ash.create(actor: actor)

      {:ok, _cfv} =
        CustomFieldValue
        |> Ash.Changeset.for_create(:create, %{
          member_id: member.id,
          custom_field_id: custom_field.id,
          value: %{"_union_type" => "email", "_union_value" => "private@example.com"}
        })
        |> Ash.create(actor: actor)

      conn = conn_with_oidc_user(conn)
      {:ok, _view, html} = live(conn, ~p"/members/#{member}")

      # Should contain mailto link
      assert html =~ ~s(href="mailto:private@example.com")
      assert html =~ "private@example.com"
    end
  end
end
