defmodule Mv.SeedsTest do
  @moduledoc """
  Minimal test suite for database seeds.

  This test suite focuses on critical deployment requirements:
  - Seeds run without errors (smoke test)
  - Seeds are idempotent (can be run multiple times)
  - Critical bootstrap invariants are met (Admin user, system roles)

  ## Removed Tests

  The following tests were removed to reduce test execution time.
  Their functionality is covered by domain-specific tests:

  - Member/fee type distribution tests → covered by `membership_fees/*_test.exs`
  - Cycle status variation tests → covered by `membership_fees/cycle_generator_test.exs`
  - Detailed role configuration tests → covered by `authorization/*_test.exs`
  - Permission set validation → covered by `authorization/permission_sets_test.exs`

  See `docs/test-optimization-seeds.md` for detailed rationale and coverage mapping.
  """

  use Mv.DataCase, async: false

  require Ash.Query

  # Module attribute to track if seeds have been run
  # This allows us to run seeds once per test module while respecting sandbox isolation
  @seeds_run_key :seeds_test_run

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

    # Run seeds once per test process (due to sandbox isolation, each test runs in its own process)
    # Process.get/put ensures seeds are only executed once per test process, not once per test
    # Note: With async: false and sandbox isolation, this effectively runs seeds once per test,
    # but the guard prevents multiple executions within the same test process if setup is called multiple times
    unless Process.get(@seeds_run_key) do
      Code.eval_file("priv/repo/seeds.exs")
      Process.put(@seeds_run_key, true)
    end

    %{actor: system_actor}
  end

  describe "Seeds script" do
    @tag :slow
    test "runs successfully and creates basic data", %{actor: actor} do
      # Smoke test: verify seeds created essential data structures
      {:ok, users} = Ash.read(Mv.Accounts.User, actor: actor)
      {:ok, members} = Ash.read(Mv.Membership.Member, actor: actor)
      {:ok, custom_fields} = Ash.read(Mv.Membership.CustomField, actor: actor)
      {:ok, roles} = Ash.read(Mv.Authorization.Role, domain: Mv.Authorization, authorize?: false)

      assert not Enum.empty?(users), "Seeds should create at least one user"
      assert not Enum.empty?(members), "Seeds should create at least one member"
      assert not Enum.empty?(custom_fields), "Seeds should create at least one custom field"
      assert length(roles) >= 5, "Seeds should create at least 5 authorization roles"
    end

    @tag :slow
    test "is idempotent when run multiple times", %{actor: actor} do
      # Seeds already run once in setup - count current state
      {:ok, users_count_1} = Ash.read(Mv.Accounts.User, actor: actor)
      {:ok, members_count_1} = Ash.read(Mv.Membership.Member, actor: actor)

      {:ok, roles_count_1} =
        Ash.read(Mv.Authorization.Role, domain: Mv.Authorization, authorize?: false)

      # Run seeds again - should not raise errors and should be idempotent
      assert Code.eval_file("priv/repo/seeds.exs")

      # Count records again - should be the same (upsert, not duplicate)
      {:ok, users_count_2} = Ash.read(Mv.Accounts.User, actor: actor)
      {:ok, members_count_2} = Ash.read(Mv.Membership.Member, actor: actor)

      {:ok, roles_count_2} =
        Ash.read(Mv.Authorization.Role, domain: Mv.Authorization, authorize?: false)

      assert length(users_count_1) == length(users_count_2),
             "Users count should remain same after re-running seeds"

      assert length(members_count_1) == length(members_count_2),
             "Members count should remain same after re-running seeds"

      assert length(roles_count_1) == length(roles_count_2),
             "Roles count should remain same after re-running seeds"
    end
  end

  describe "Critical bootstrap invariants" do
    test "Admin user has Admin role and can authenticate", %{actor: _actor} do
      # Critical: Without this, initial system setup fails
      admin_email = System.get_env("ADMIN_EMAIL") || "admin@localhost"

      {:ok, admin_user} =
        Mv.Accounts.User
        |> Ash.Query.filter(email == ^admin_email)
        |> Ash.read_one(domain: Mv.Accounts, authorize?: false)

      assert admin_user != nil, "Admin user must exist after seeds run"

      {:ok, admin_user_with_role} =
        Ash.load(admin_user, :role, domain: Mv.Accounts, authorize?: false)

      assert admin_user_with_role.role != nil, "Admin user must have a role assigned"
      assert admin_user_with_role.role.name == "Admin", "Admin user must have Admin role"

      assert admin_user_with_role.role.permission_set_name == "admin",
             "Admin role must have admin permission set"
    end

    test "Mitglied system role exists and is correctly configured" do
      # Critical: Default role for new users - system breaks without this
      {:ok, mitglied} =
        Mv.Authorization.Role
        |> Ash.Query.filter(name == "Mitglied")
        |> Ash.read_one(domain: Mv.Authorization, authorize?: false)

      assert mitglied != nil, "Mitglied role must exist"
      assert mitglied.is_system_role == true, "Mitglied role must be marked as system role"

      assert mitglied.permission_set_name == "own_data",
             "Mitglied role must have own_data permission set"
    end
  end
end
