defmodule MvWeb.GroupLive.IntegrationTest do
  @moduledoc """
  Integration tests for complete group management workflows.

  Tests cover:
  - Complete workflows (Create → View → Edit → Delete)
  - Slug-based navigation
  - Member-group associations
  - URL persistence
  """
  use MvWeb.ConnCase, async: false
  import Phoenix.LiveViewTest
  require Ash.Query
  import Ash.Expr
  use Gettext, backend: MvWeb.Gettext

  alias Mv.Membership
  alias Mv.Fixtures

  describe "complete workflow" do
    test "create → view via slug → edit → view via slug (slug unchanged)", %{
      conn: conn,
      current_user: current_user
    } do
      # Create group
      {:ok, view, _html} = live(conn, "/groups/new")

      form_data = %{
        "name" => "Workflow Test Group",
        "description" => "Initial description"
      }

      view
      |> form("#group-form", group: form_data)
      |> render_submit()

      # Get the created group by name using current user (tests authorization)
      {:ok, groups} = Membership.list_groups(actor: current_user)
      group = Enum.find(groups, &(&1.name == "Workflow Test Group"))
      original_slug = group.slug

      # View via slug
      {:ok, _view, html} = live(conn, "/groups/#{group.slug}")

      assert html =~ "Workflow Test Group"
      assert html =~ "Initial description"

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

      form_data = %{
        "name" => "Updated Workflow Test Group",
        "description" => "Updated description"
      }

      view
      |> form("#group-form", group: form_data)
      |> render_submit()

      # View again via slug (should still work with original slug)
      {:ok, _view, html} = live(conn, "/groups/#{original_slug}")

      assert html =~ "Updated Workflow Test Group"
      assert html =~ "Updated description"
      # OR-chain: slug may appear as UUID or normalized slug in copy
      assert html =~ original_slug or html =~ "workflow-test-group"
    end

    test "create group → add members → view (member count updated)", %{
      conn: conn,
      current_user: current_user
    } do
      # Create group
      {:ok, view, _html} = live(conn, "/groups/new")

      form_data = %{
        "name" => "Member Test Group"
      }

      view
      |> form("#group-form", group: form_data)
      |> render_submit()

      # Get the created group using current user (tests authorization)
      {:ok, groups} = Membership.list_groups(actor: current_user)
      group = Enum.find(groups, &(&1.name == "Member Test Group"))

      # Add members to group (use system_actor for test data setup)
      system_actor = Mv.Helpers.SystemActor.get_system_actor()
      member1 = Fixtures.member_fixture()
      member2 = Fixtures.member_fixture()

      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
      )

      # View group via slug
      {:ok, _view, html} = live(conn, "/groups/#{group.slug}")

      # OR-chain for i18n (Members/Mitglieder); member names may be first or last
      assert html =~ "2" or html =~ gettext("Members") or html =~ "Mitglieder"
      assert html =~ member1.first_name or html =~ member1.last_name
      assert html =~ member2.first_name or html =~ member2.last_name
    end

    test "create group → add members → delete (cascade works)", %{
      conn: conn,
      current_user: current_user
    } do
      # Create group
      {:ok, view, _html} = live(conn, "/groups/new")

      form_data = %{
        "name" => "Delete Test Group"
      }

      view
      |> form("#group-form", group: form_data)
      |> render_submit()

      # Get the created group using current user (tests authorization)
      {:ok, groups} = Membership.list_groups(actor: current_user)
      group = Enum.find(groups, &(&1.name == "Delete Test Group"))

      # Add member to group (use system_actor for test data setup)
      system_actor = Mv.Helpers.SystemActor.get_system_actor()
      member = Fixtures.member_fixture()

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

      # Delete group (via UI - would need delete confirmation modal test)
      # For now, test via API that cascade works
      # Use current_user to test authorization (admin can delete)
      :ok = Membership.destroy_group(group, actor: current_user)

      # Verify member still exists (use system_actor for verification - this is test verification, not user action)
      system_actor = Mv.Helpers.SystemActor.get_system_actor()
      {:ok, member_reloaded} = Ash.get(Mv.Membership.Member, member.id, actor: system_actor)
      assert member_reloaded != nil

      # Verify member-group association is deleted
      {:ok, mgs} =
        Ash.read(
          Mv.Membership.MemberGroup
          |> Ash.Query.filter(expr(group_id == ^group.id)),
          actor: system_actor,
          domain: Mv.Membership
        )

      assert mgs == []
    end
  end

  describe "slug-based navigation" do
    test "links to group detail use slug (not ID)", %{conn: conn} do
      group = Fixtures.group_fixture(%{name: "Navigation Test Group"})

      {:ok, _view, html} = live(conn, "/groups")

      # Links should use slug, not UUID
      assert html =~ "/groups/#{group.slug}"
      refute html =~ "/groups/#{group.id}"
    end

    test "deep links to group detail per slug work", %{conn: conn} do
      group = Fixtures.group_fixture(%{name: "Deep Link Test"})

      # Direct navigation to slug URL
      {:ok, _view, html} = live(conn, "/groups/#{group.slug}")

      assert html =~ "Deep Link Test"
    end

    test "browser back button works correctly", %{conn: conn} do
      group = Fixtures.group_fixture()

      # Navigate to group detail
      {:ok, _view1, _html} = live(conn, "/groups/#{group.slug}")

      # Navigate to edit
      {:ok, view2, _html} = live(conn, "/groups/#{group.slug}/edit")

      # Browser back should work (tested via navigation)
      assert view2 != nil
    end
  end

  describe "URL persistence" do
    test "slug-based URLs persist across page reloads", %{conn: conn} do
      group = Fixtures.group_fixture(%{name: "Persistent URL Test"})

      # First visit
      {:ok, _view1, html1} = live(conn, "/groups/#{group.slug}")

      assert html1 =~ "Persistent URL Test"

      # Simulate page reload (new connection)
      {:ok, _view2, html2} = live(conn, "/groups/#{group.slug}")

      assert html2 =~ "Persistent URL Test"
    end
  end
end
