defmodule Mv.Accounts.UserMemberDeletionTest do
  @moduledoc """
  Tests for ON DELETE SET NULL constraint on users.member_id.
  When a member is deleted, the linked user should remain but with member_id set to NULL.
  """
  use Mv.DataCase, async: true
  alias Mv.Accounts
  alias Mv.Membership

  describe "User remains when linked Member is deleted (ON DELETE SET NULL)" do
    @valid_user_attrs %{
      email: "test@example.com"
    }

    @valid_member_attrs %{
      first_name: "John",
      last_name: "Doe",
      email: "john@example.com"
    }

    setup do
      system_actor = Mv.Helpers.SystemActor.get_system_actor()
      %{actor: system_actor}
    end

    test "deleting a member sets the user's member_id to NULL", %{actor: actor} do
      # Create a member
      {:ok, member} = Membership.create_member(@valid_member_attrs, actor: actor)

      # Create a user linked to the member
      {:ok, user} =
        Accounts.create_user(Map.put(@valid_user_attrs, :member, %{id: member.id}), actor: actor)

      # Verify the relationship is established
      {:ok, user_before_delete} =
        Ash.get(Mv.Accounts.User, user.id, actor: actor, load: [:member])

      assert user_before_delete.member_id == member.id
      assert user_before_delete.member.id == member.id

      # Delete the member
      :ok = Membership.destroy_member(member, actor: actor)

      # Verify the user still exists but member_id is NULL
      {:ok, user_after_delete} =
        Ash.get(Mv.Accounts.User, user.id, actor: actor, load: [:member])

      assert user_after_delete.id == user.id
      assert user_after_delete.member_id == nil
      assert user_after_delete.member == nil
    end

    test "user can be linked to a new member after old member is deleted", %{actor: actor} do
      # Create first member
      {:ok, member1} = Membership.create_member(@valid_member_attrs, actor: actor)

      # Create user linked to first member
      {:ok, user} =
        Accounts.create_user(Map.put(@valid_user_attrs, :member, %{id: member1.id}), actor: actor)

      assert user.member_id == member1.id

      # Delete first member
      :ok = Membership.destroy_member(member1, actor: actor)

      # Reload user from database to get updated member_id (should be NULL)
      {:ok, user_after_delete} = Ash.get(Mv.Accounts.User, user.id, actor: actor)
      assert user_after_delete.member_id == nil

      # Create second member
      {:ok, member2} =
        Membership.create_member(
          %{
            first_name: "Jane",
            last_name: "Smith",
            email: "jane@example.com"
          },
          actor: actor
        )

      # Link user to second member (use reloaded user)
      {:ok, updated_user} =
        Accounts.update_user(user_after_delete, %{member: %{id: member2.id}}, actor: actor)

      # Verify new relationship
      {:ok, final_user} =
        Ash.get(Mv.Accounts.User, updated_user.id, actor: actor, load: [:member])

      assert final_user.member_id == member2.id
      assert final_user.member.id == member2.id
    end

    test "member without linked user can be deleted normally", %{actor: actor} do
      {:ok, member} = Membership.create_member(@valid_member_attrs, actor: actor)

      # Delete member (no users linked)
      assert :ok = Membership.destroy_member(member, actor: actor)

      # Verify member is deleted
      assert {:error, _} = Ash.get(Mv.Membership.Member, member.id, actor: actor)
    end
  end
end
