defmodule MvWeb.MemberLive.ShowGroupsDisplayTest do
  @moduledoc """
  Tests for displaying groups in the member detail view (Issue #374).

  Tests cover:
  - Groups in Personal Data (with and without groups)
  - Group links with correct names and links to group detail pages
  - Edge cases (one group, many groups)
  - Security: groups visible only when user may view member
  - Accessibility: group links have aria-label for screen readers

  ## Note on async
  async: false to avoid PostgreSQL deadlocks when creating members and groups
  in the same test run (same as IndexGroupsDisplayTest).
  """
  use MvWeb.ConnCase, async: false
  import Phoenix.LiveViewTest
  require Ash.Query
  use Gettext, backend: MvWeb.Gettext

  alias Mv.Membership.{Group, MemberGroup}

  describe "groups section" do
    setup do
      actor = Mv.Helpers.SystemActor.get_system_actor()

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

      %{member: member, actor: actor}
    end

    test "displays Groups section when member has at least one group", %{
      conn: conn,
      member: member,
      actor: actor
    } do
      {:ok, group} = create_group(actor, "Board Members")
      {:ok, _mg} = add_member_to_group(member, group, actor)

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

      assert html =~ gettext("Groups")
      assert html =~ group.name
    end

    test "displays all group links with correct names when member is in multiple groups", %{
      conn: conn,
      member: member,
      actor: actor
    } do
      {:ok, group1} = create_group(actor, "Board Members")
      {:ok, group2} = create_group(actor, "Active Members")
      {:ok, _mg1} = add_member_to_group(member, group1, actor)
      {:ok, _mg2} = add_member_to_group(member, group2, actor)

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

      assert html =~ gettext("Groups")
      assert html =~ group1.name
      assert html =~ group2.name
    end

    test "displays Groups section when member has no groups (empty state)", %{
      conn: conn,
      member: member
    } do
      conn = conn_with_oidc_user(conn)
      {:ok, _view, html} = live(conn, ~p"/members/#{member}")

      # Groups are in Personal Data; label "Groups" and empty state "No groups" must be present
      assert html =~ gettext("Groups")
      assert html =~ gettext("No groups")
    end

    test "renders all group names when member has multiple groups", %{
      conn: conn,
      member: member,
      actor: actor
    } do
      {:ok, group1} = create_group(actor, "Alpha")
      {:ok, group2} = create_group(actor, "Beta")
      {:ok, _mg1} = add_member_to_group(member, group1, actor)
      {:ok, _mg2} = add_member_to_group(member, group2, actor)

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

      assert html =~ "Alpha"
      assert html =~ "Beta"
    end
  end

  describe "groups section links" do
    setup do
      actor = Mv.Helpers.SystemActor.get_system_actor()

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

      {:ok, group} = create_group(actor, "Board Members")
      {:ok, _mg} = add_member_to_group(member, group, actor)
      %{member: member, group: group}
    end

    test "each group link goes to group detail page with correct slug", %{
      conn: conn,
      member: member,
      group: group
    } do
      conn = conn_with_oidc_user(conn)
      {:ok, view, _html} = live(conn, ~p"/members/#{member}")

      # Link to group detail: /groups/:slug (slug is URL-friendly, e.g. "board-members")
      assert has_element?(view, "a[href*='/groups/#{group.slug}']", group.name)
    end

    test "clicking group link navigates to group detail page", %{
      conn: conn,
      member: member,
      group: group
    } do
      conn = conn_with_oidc_user(conn)
      {:ok, view, _html} = live(conn, ~p"/members/#{member}")

      view
      |> element("a[href*='/groups/#{group.slug}']")
      |> render_click()

      assert_redirect(view, ~p"/groups/#{group.slug}")
    end
  end

  describe "groups section edge cases" do
    setup do
      actor = Mv.Helpers.SystemActor.get_system_actor()

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

      %{member: member, actor: actor}
    end

    test "member in exactly one group shows single link", %{
      conn: conn,
      member: member,
      actor: actor
    } do
      {:ok, group} = create_group(actor, "Solo Group")
      {:ok, _mg} = add_member_to_group(member, group, actor)

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

      assert html =~ gettext("Groups")
      assert html =~ group.name
    end

    test "member in many groups shows all group links", %{
      conn: conn,
      member: member,
      actor: actor
    } do
      group_names = Enum.map(1..5, fn i -> "Group #{i}" end)

      groups =
        Enum.map(group_names, fn name ->
          {:ok, g} = create_group(actor, name)
          g
        end)

      for g <- groups do
        {:ok, _mg} = add_member_to_group(member, g, actor)
      end

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

      assert html =~ gettext("Groups")

      for name <- group_names do
        assert html =~ name
      end
    end
  end

  describe "groups section with read_only user" do
    @tag role: :read_only
    test "user with read permission sees Groups section", %{conn: conn} do
      actor = Mv.Helpers.SystemActor.get_system_actor()

      {:ok, member} =
        create_member(actor, %{
          first_name: "Diana",
          last_name: "Davis",
          email: "diana@example.com"
        })

      {:ok, group} = create_group(actor, "Readers")
      {:ok, _mg} = add_member_to_group(member, group, actor)

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

      assert html =~ gettext("Groups")
      assert html =~ group.name
    end
  end

  describe "groups section accessibility" do
    setup do
      actor = Mv.Helpers.SystemActor.get_system_actor()

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

      {:ok, group} = create_group(actor, "A11y Group")
      {:ok, _mg} = add_member_to_group(member, group, actor)
      %{member: member, group: group}
    end

    test "group links have aria-label for screen readers", %{
      conn: conn,
      member: member,
      group: group
    } do
      conn = conn_with_oidc_user(conn)
      {:ok, view, html} = live(conn, ~p"/members/#{member}")

      assert html =~ group.name

      # Group link has aria-label indicating group membership for screen readers
      assert has_element?(view, "a[aria-label*='#{group.name}']")
    end
  end

  # Helpers to reduce setup duplication (create member/group, assign member to group).
  defp create_member(actor, attrs) do
    Mv.Membership.create_member(attrs, actor: actor)
  end

  defp create_group(actor, name) do
    Group
    |> Ash.Changeset.for_create(:create, %{name: name})
    |> Ash.create(actor: actor)
  end

  defp add_member_to_group(member, group, actor) do
    MemberGroup
    |> Ash.Changeset.for_create(:create, %{member_id: member.id, group_id: group.id})
    |> Ash.create(actor: actor)
  end
end
