defmodule MvWeb.MemberLive.IndexGroupsFilterTest do
  @moduledoc """
  Tests for filtering members by group in the member overview.

  Uses the filter dropdown (MemberFilterComponent) with one row per group:
  All / Yes / No (per group). Multiple active group filters combine with AND
  (member must match all selected group conditions).
  """
  # async: false to prevent PostgreSQL deadlocks when creating members and groups
  use MvWeb.ConnCase, async: false
  import Phoenix.LiveViewTest
  require Ash.Query

  alias Mv.Membership.{Group, MemberGroup}

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

    {: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
      )

    {:ok, member3} =
      Mv.Membership.create_member(
        %{first_name: "Charlie", last_name: "Clark", email: "charlie@example.com"},
        actor: system_actor
      )

    {:ok, group1} =
      Group
      |> Ash.Changeset.for_create(:create, %{name: "Board Members"})
      |> Ash.create(actor: system_actor)

    {:ok, group2} =
      Group
      |> Ash.Changeset.for_create(:create, %{name: "Active Members"})
      |> Ash.create(actor: system_actor)

    {:ok, _mg1} =
      MemberGroup
      |> Ash.Changeset.for_create(:create, %{member_id: member1.id, group_id: group1.id})
      |> Ash.create(actor: system_actor)

    {:ok, _mg2} =
      MemberGroup
      |> Ash.Changeset.for_create(:create, %{member_id: member2.id, group_id: group2.id})
      |> Ash.create(actor: system_actor)

    %{member1: member1, member2: member2, member3: member3, group1: group1, group2: group2}
  end

  defp open_filter_and_set_group(view, group_id, value) do
    view
    |> element("button[aria-label='Filter members']")
    |> render_click()

    key = "group_#{group_id}"

    view
    |> element("[data-testid='member-filter-form']")
    |> render_change(%{key => value, "payment_filter" => "all"})

    # Force LiveView to process {:group_filter_changed, ...} (render triggers mailbox processing)
    _ = render(view)
    assert_patch(view)
  end

  test "filter All (default) shows all members", %{
    conn: conn,
    member1: m1,
    member2: m2,
    member3: m3
  } do
    conn = conn_with_oidc_user(conn)
    {:ok, _view, html} = live(conn, "/members")
    assert html =~ m1.first_name
    assert html =~ m2.first_name
    assert html =~ m3.first_name
  end

  test "filter group1 Yes shows only members in group1", %{
    conn: conn,
    member1: m1,
    member2: m2,
    member3: m3,
    group1: group1
  } do
    conn = conn_with_oidc_user(conn)
    {:ok, view, _html} = live(conn, "/members")

    open_filter_and_set_group(view, group1.id, "in")

    html = render(view)
    assert html =~ m1.first_name
    refute html =~ m2.first_name
    refute html =~ m3.first_name
  end

  test "filter group1 No shows only members not in group1", %{
    conn: conn,
    member1: m1,
    member2: m2,
    member3: m3,
    group1: group1
  } do
    conn = conn_with_oidc_user(conn)
    {:ok, view, _html} = live(conn, "/members")

    open_filter_and_set_group(view, group1.id, "not_in")

    html = render(view)
    refute html =~ m1.first_name
    assert html =~ m2.first_name
    assert html =~ m3.first_name
  end

  test "filter persists in URL parameters", %{
    conn: conn,
    member1: m1,
    member2: m2,
    member3: m3,
    group1: group1
  } do
    conn = conn_with_oidc_user(conn)
    {:ok, view, _html} = live(conn, "/members")

    open_filter_and_set_group(view, group1.id, "in")

    html = render(view)
    assert html =~ m1.first_name
    refute html =~ m2.first_name
    refute html =~ m3.first_name

    {:ok, _view2, html2} = live(conn, "/members?group_#{group1.id}=in")
    assert html2 =~ m1.first_name
    refute html2 =~ m2.first_name
    refute html2 =~ m3.first_name
  end

  test "filter is restored from URL on load", %{
    conn: conn,
    member1: m1,
    member2: m2,
    member3: m3,
    group1: group1
  } do
    conn = conn_with_oidc_user(conn)
    {:ok, _view, html} = live(conn, "/members?group_#{group1.id}=in")
    assert html =~ m1.first_name
    refute html =~ m2.first_name
    refute html =~ m3.first_name
  end
end
