defmodule MvWeb.MemberLive.IndexCustomFieldsDisplayTest do
  @moduledoc """
  Tests for displaying custom fields in the member overview.

  Tests cover:
  - Custom fields with show_in_overview: true are displayed
  - Custom fields with show_in_overview: false are not displayed
  - Multiple custom fields with show_in_overview: true are all displayed
  - Custom field values are correctly formatted for different types
  - Members without custom field values show empty cell or "-"
  """
  # async: false to prevent PostgreSQL deadlocks when creating members and custom fields
  use MvWeb.ConnCase, async: false
  import Phoenix.LiveViewTest
  require Ash.Query

  alias Mv.Membership.{CustomField, CustomFieldValue}

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

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

    {:ok, member2} =
      Mv.Membership.create_member(
        %{first_name: "Bob", last_name: "Brown", email: "bob@example.com"},
        actor: system_actor
      )

    # Create custom fields
    {:ok, field_show_string} =
      CustomField
      |> Ash.Changeset.for_create(:create, %{
        name: "phone_mobile",
        value_type: :string,
        show_in_overview: true
      })
      |> Ash.create(actor: system_actor)

    {:ok, field_hide} =
      CustomField
      |> Ash.Changeset.for_create(:create, %{
        name: "internal_note",
        value_type: :string,
        show_in_overview: false
      })
      |> Ash.create(actor: system_actor)

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

    {:ok, field_show_boolean} =
      CustomField
      |> Ash.Changeset.for_create(:create, %{
        name: "newsletter",
        value_type: :boolean,
        show_in_overview: true
      })
      |> Ash.create(actor: system_actor)

    {:ok, field_show_date} =
      CustomField
      |> Ash.Changeset.for_create(:create, %{
        name: "birthday",
        value_type: :date,
        show_in_overview: true
      })
      |> Ash.create(actor: system_actor)

    {:ok, field_show_email} =
      CustomField
      |> Ash.Changeset.for_create(:create, %{
        name: "secondary_email",
        value_type: :email,
        show_in_overview: true
      })
      |> Ash.create(actor: system_actor)

    # Create custom field values for member1
    {:ok, _cfv1} =
      CustomFieldValue
      |> Ash.Changeset.for_create(:create, %{
        member_id: member1.id,
        custom_field_id: field_show_string.id,
        value: %{"_union_type" => "string", "_union_value" => "+49123456789"}
      })
      |> Ash.create(actor: system_actor)

    {:ok, _cfv2} =
      CustomFieldValue
      |> Ash.Changeset.for_create(:create, %{
        member_id: member1.id,
        custom_field_id: field_show_integer.id,
        value: %{"_union_type" => "integer", "_union_value" => 12_345}
      })
      |> Ash.create(actor: system_actor)

    {:ok, _cfv3} =
      CustomFieldValue
      |> Ash.Changeset.for_create(:create, %{
        member_id: member1.id,
        custom_field_id: field_show_boolean.id,
        value: %{"_union_type" => "boolean", "_union_value" => true}
      })
      |> Ash.create(actor: system_actor)

    {:ok, _cfv4} =
      CustomFieldValue
      |> Ash.Changeset.for_create(:create, %{
        member_id: member1.id,
        custom_field_id: field_show_date.id,
        value: %{"_union_type" => "date", "_union_value" => ~D[1990-05-15]}
      })
      |> Ash.create(actor: system_actor)

    {:ok, _cfv5} =
      CustomFieldValue
      |> Ash.Changeset.for_create(:create, %{
        member_id: member1.id,
        custom_field_id: field_show_email.id,
        value: %{"_union_type" => "email", "_union_value" => "alice.private@example.com"}
      })
      |> Ash.create(actor: system_actor)

    # Create hidden custom field value (should not be displayed)
    {:ok, _cfv_hidden} =
      CustomFieldValue
      |> Ash.Changeset.for_create(:create, %{
        member_id: member1.id,
        custom_field_id: field_hide.id,
        value: %{"_union_type" => "string", "_union_value" => "Internal note"}
      })
      |> Ash.create(actor: system_actor)

    %{
      member1: member1,
      member2: member2,
      field_show_string: field_show_string,
      field_hide: field_hide,
      field_show_integer: field_show_integer,
      field_show_boolean: field_show_boolean,
      field_show_date: field_show_date,
      field_show_email: field_show_email
    }
  end

  @tag :slow
  test "displays custom field with show_in_overview: true", %{
    conn: conn,
    member1: _member1,
    field_show_string: field
  } do
    conn = conn_with_oidc_user(conn)
    {:ok, _view, html} = live(conn, "/members")

    # Check that the custom field column header is displayed
    assert html =~ field.name

    # Check that the value is displayed
    assert html =~ "+49123456789"
  end

  test "does not display custom field with show_in_overview: false", %{
    conn: conn,
    member1: _member1,
    field_hide: field
  } do
    conn = conn_with_oidc_user(conn)
    {:ok, _view, html} = live(conn, "/members")

    # Check that the hidden custom field column header is NOT displayed
    refute html =~ field.name

    # Check that the value is NOT displayed
    refute html =~ "Internal note"
  end

  test "displays multiple custom fields with show_in_overview: true", %{
    conn: conn,
    field_show_string: field_string,
    field_show_integer: field_integer,
    field_show_boolean: field_boolean
  } do
    conn = conn_with_oidc_user(conn)
    {:ok, _view, html} = live(conn, "/members")

    # Check that all visible custom field column headers are displayed
    assert html =~ field_string.name
    assert html =~ field_integer.name
    assert html =~ field_boolean.name
  end

  test "formats string custom field values correctly", %{conn: conn, member1: _member1} do
    conn = conn_with_oidc_user(conn)
    {:ok, _view, html} = live(conn, "/members")

    assert html =~ "+49123456789"
  end

  test "formats integer custom field values correctly", %{conn: conn, member1: _member1} do
    conn = conn_with_oidc_user(conn)
    {:ok, _view, html} = live(conn, "/members")

    assert html =~ "12345"
  end

  test "formats boolean custom field values correctly", %{conn: conn, member1: _member1} do
    conn = conn_with_oidc_user(conn)
    {:ok, _view, html} = live(conn, "/members")

    # Boolean should be displayed as "Yes" or "No" or similar
    # Check for true representation
    assert html =~ "true" or html =~ "Yes" or html =~ "Ja"
  end

  @tag :slow
  test "formats date custom field values correctly", %{conn: conn, member1: _member1} do
    conn = conn_with_oidc_user(conn)
    {:ok, _view, html} = live(conn, "/members")

    # Date should be displayed in European format (dd.mm.yyyy)
    assert html =~ "15.05.1990"
  end

  @tag :slow
  test "formats email custom field values correctly", %{conn: conn, member1: _member1} do
    conn = conn_with_oidc_user(conn)
    {:ok, _view, html} = live(conn, "/members")

    assert html =~ "alice.private@example.com"
  end

  test "shows empty cell for members without custom field values", %{
    conn: conn,
    member2: _member2,
    field_show_string: field
  } do
    conn = conn_with_oidc_user(conn)
    {:ok, _view, html} = live(conn, "/members")

    # The custom field column should exist
    assert html =~ field.name

    # Member2 should exist in the table (first_name and last_name are in separate columns)
    assert html =~ "Bob"
    assert html =~ "Brown"

    # The value from member1 should appear (phone number)
    assert html =~ "+49123456789"

    # Note: Member2 doesn't have this custom field value, so the cell is empty
    # The implementation shows "" for missing values, which is the expected behavior
  end
end
