defmodule MvWeb.GroupLive.ShowIntegrationTest do
  @moduledoc """
  Integration tests for Add/Remove Member functionality.
  Tests data consistency, database operations, and multiple operations.
  """

  use MvWeb.ConnCase, async: false
  import Phoenix.LiveViewTest
  use Gettext, backend: MvWeb.Gettext

  alias Mv.Membership
  alias Mv.Fixtures

  describe "data consistency" do
    test "member appears in group after add (verified in database)", %{conn: conn} do
      system_actor = Mv.Helpers.SystemActor.get_system_actor()
      group = Fixtures.group_fixture()

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

      {:ok, view, _html} = live(conn, "/groups/#{group.slug}")

      # Add member via UI
      view
      |> element("button", "Add Member")
      |> render_click()

      view
      |> element("#member-search-input")
      |> render_focus()

      # phx-change is on the form, so we need to trigger it via the form
      view
      |> element("form[phx-change='search_members']")
      |> render_change(%{"member_search" => "Alice"})

      view
      |> element("[data-member-id='#{member.id}']")
      |> render_click()

      view
      |> element("button[phx-click='add_selected_members']")
      |> render_click()

      # Verify in database
      require Ash.Query

      query =
        Mv.Membership.Group
        |> Ash.Query.filter(slug == ^group.slug)
        |> Ash.Query.load([:members])

      {:ok, updated_group} = Ash.read_one(query, actor: system_actor, domain: Mv.Membership)

      # Member should be in group
      assert Enum.any?(updated_group.members, &(&1.id == member.id))
    end

    test "member disappears from group after remove (verified in database)", %{conn: conn} do
      system_actor = Mv.Helpers.SystemActor.get_system_actor()
      group = Fixtures.group_fixture()

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

      # Add member to group
      Membership.create_member_group(%{member_id: member.id, group_id: group.id},
        actor: system_actor
      )

      {:ok, view, _html} = live(conn, "/groups/#{group.slug}")

      # Remove member via UI
      view
      |> element("button[phx-click='remove_member'][phx-value-member_id='#{member.id}']")
      |> render_click()

      # Verify in database
      require Ash.Query

      query =
        Mv.Membership.Group
        |> Ash.Query.filter(slug == ^group.slug)
        |> Ash.Query.load([:members])

      {:ok, updated_group} = Ash.read_one(query, actor: system_actor, domain: Mv.Membership)

      # Member should NOT be in group
      refute Enum.any?(updated_group.members, &(&1.id == member.id))
    end

    test "MemberGroup association is created correctly", %{conn: conn} do
      system_actor = Mv.Helpers.SystemActor.get_system_actor()
      group = Fixtures.group_fixture()

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

      {:ok, view, _html} = live(conn, "/groups/#{group.slug}")

      # Add member
      view
      |> element("button", "Add Member")
      |> render_click()

      view
      |> element("#member-search-input")
      |> render_focus()

      # phx-change is on the form, so we need to trigger it via the form
      view
      |> element("form[phx-change='search_members']")
      |> render_change(%{"member_search" => "Charlie"})

      view
      |> element("[data-member-id='#{member.id}']")
      |> render_click()

      view
      |> element("button[phx-click='add_selected_members']")
      |> render_click()

      # Verify MemberGroup association exists
      require Ash.Query

      {:ok, member_groups} =
        Ash.read(
          Mv.Membership.MemberGroup
          |> Ash.Query.filter(member_id == ^member.id and group_id == ^group.id),
          actor: system_actor,
          domain: Mv.Membership
        )

      assert length(member_groups) == 1
      assert hd(member_groups).member_id == member.id
      assert hd(member_groups).group_id == group.id
    end

    test "MemberGroup association is deleted correctly", %{conn: conn} do
      system_actor = Mv.Helpers.SystemActor.get_system_actor()
      group = Fixtures.group_fixture()

      {:ok, member} =
        Membership.create_member(
          %{
            first_name: "David",
            last_name: "Wilson",
            email: "david@example.com"
          },
          actor: system_actor
        )

      # Add member first
      Membership.create_member_group(%{member_id: member.id, group_id: group.id},
        actor: system_actor
      )

      {:ok, view, _html} = live(conn, "/groups/#{group.slug}")

      # Remove member
      view
      |> element("button[phx-click='remove_member'][phx-value-member_id='#{member.id}']")
      |> render_click()

      # Verify MemberGroup association is deleted
      require Ash.Query

      {:ok, member_groups} =
        Ash.read(
          Mv.Membership.MemberGroup
          |> Ash.Query.filter(member_id == ^member.id and group_id == ^group.id),
          actor: system_actor,
          domain: Mv.Membership
        )

      assert member_groups == []
    end

    test "member itself is NOT deleted (only association)", %{conn: conn} do
      system_actor = Mv.Helpers.SystemActor.get_system_actor()
      group = Fixtures.group_fixture()

      {:ok, member} =
        Membership.create_member(
          %{
            first_name: "Eve",
            last_name: "Davis",
            email: "eve@example.com"
          },
          actor: system_actor
        )

      # Add member to group
      Membership.create_member_group(%{member_id: member.id, group_id: group.id},
        actor: system_actor
      )

      {:ok, view, _html} = live(conn, "/groups/#{group.slug}")

      # Remove member from group
      view
      |> element("button[phx-click='remove_member']", "")
      |> render_click()

      # Verify member still exists
      {:ok, member_after_remove} =
        Ash.get(Mv.Membership.Member, member.id, actor: system_actor)

      assert member_after_remove.id == member.id
      assert member_after_remove.first_name == "Eve"
    end
  end

  describe "multiple operations" do
    test "multiple members can be added sequentially", %{conn: conn} do
      system_actor = Mv.Helpers.SystemActor.get_system_actor()
      group = Fixtures.group_fixture()

      {:ok, member1} =
        Membership.create_member(
          %{
            first_name: "Frank",
            last_name: "Moore",
            email: "frank@example.com"
          },
          actor: system_actor
        )

      {:ok, member2} =
        Membership.create_member(
          %{
            first_name: "Grace",
            last_name: "Taylor",
            email: "grace@example.com"
          },
          actor: system_actor
        )

      {:ok, view, _html} = live(conn, "/groups/#{group.slug}")

      # Add first member
      view
      |> element("button", "Add Member")
      |> render_click()

      view
      |> element("#member-search-input")
      |> render_focus()

      # phx-change is on the form, so we need to trigger it via the form
      view
      |> element("form[phx-change='search_members']")
      |> render_change(%{"member_search" => "Frank"})

      view
      |> element("[data-member-id='#{member1.id}']")
      |> render_click()

      view
      |> element("button[phx-click='add_selected_members']")
      |> render_click()

      # Add second member
      view
      |> element("button", "Add Member")
      |> render_click()

      view
      |> element("#member-search-input")
      |> render_focus()

      # phx-change is on the form, so we need to trigger it via the form
      view
      |> element("form[phx-change='search_members']")
      |> render_change(%{"member_search" => "Grace"})

      view
      |> element("[data-member-id='#{member2.id}']")
      |> render_click()

      view
      |> element("button[phx-click='add_selected_members']")
      |> render_click()

      # Both members should be in list
      assert has_element?(view, "[data-testid=group-show-members-table]", "Frank")
      assert has_element?(view, "[data-testid=group-show-members-table]", "Grace")
    end

    test "multiple members can be removed sequentially", %{conn: conn} do
      system_actor = Mv.Helpers.SystemActor.get_system_actor()
      group = Fixtures.group_fixture()

      {:ok, member1} =
        Membership.create_member(
          %{
            first_name: "Henry",
            last_name: "Anderson",
            email: "henry@example.com"
          },
          actor: system_actor
        )

      {:ok, member2} =
        Membership.create_member(
          %{
            first_name: "Isabel",
            last_name: "Martinez",
            email: "isabel@example.com"
          },
          actor: system_actor
        )

      # Add both members
      Membership.create_member_group(%{member_id: member1.id, group_id: group.id},
        actor: system_actor
      )

      Membership.create_member_group(%{member_id: member2.id, group_id: group.id},
        actor: system_actor
      )

      {:ok, view, _html} = live(conn, "/groups/#{group.slug}")

      # Both should be in list initially
      assert has_element?(view, "[data-testid=group-show-members-table]", "Henry")
      assert has_element?(view, "[data-testid=group-show-members-table]", "Isabel")

      # Remove first member
      view
      |> element("button[phx-click='remove_member'][phx-value-member_id='#{member1.id}']")
      |> render_click()

      # Remove second member
      view
      |> element("button[phx-click='remove_member'][phx-value-member_id='#{member2.id}']")
      |> render_click()

      # Both should be removed
      refute has_element?(view, "[data-testid=group-show-members-table]", "Henry")
      refute has_element?(view, "[data-testid=group-show-members-table]", "Isabel")
    end

    test "add and remove can be mixed", %{conn: conn} do
      system_actor = Mv.Helpers.SystemActor.get_system_actor()
      group = Fixtures.group_fixture()

      {:ok, member1} =
        Membership.create_member(
          %{
            first_name: "Jack",
            last_name: "White",
            email: "jack@example.com"
          },
          actor: system_actor
        )

      {:ok, member2} =
        Membership.create_member(
          %{
            first_name: "Kate",
            last_name: "Black",
            email: "kate@example.com"
          },
          actor: system_actor
        )

      # Add member1 first
      Membership.create_member_group(%{member_id: member1.id, group_id: group.id},
        actor: system_actor
      )

      {:ok, view, _html} = live(conn, "/groups/#{group.slug}")

      # Add member2
      view
      |> element("button", "Add Member")
      |> render_click()

      view
      |> element("#member-search-input")
      |> render_focus()

      # phx-change is on the form, so we need to trigger it via the form
      view
      |> element("form[phx-change='search_members']")
      |> render_change(%{"member_search" => "Kate"})

      view
      |> element("[data-member-id='#{member2.id}']")
      |> render_click()

      view
      |> element("button[phx-click='add_selected_members']")
      |> render_click()

      # Remove member1
      view
      |> element("button[phx-click='remove_member'][phx-value-member_id='#{member1.id}']")
      |> render_click()

      # Only member2 should remain
      refute has_element?(view, "[data-testid=group-show-members-table]", "Jack")
      assert has_element?(view, "[data-testid=group-show-members-table]", "Kate")
    end
  end
end
