<?php

declare(strict_types=1);

namespace App\Services\Users;

use App\Enums\UserStatus;
use App\Models\User;
use App\Services\Audit\AuditEvent;
use App\Services\Audit\AuditRecorder;
use Illuminate\Support\Facades\DB;

/**
 * Closes an account.
 *
 * Closure soft-deletes the user, which keeps the row available for dispute
 * resolution and financial history while releasing the email address and seller
 * handle for reuse -- the unique indexes are scoped to live rows precisely so
 * that closing an account does not permanently burn the identifiers attached to
 * it.
 *
 * Every credential is revoked in the same transaction, because a closed account
 * whose tokens still work is not closed.
 */
final class AccountCloser
{
    public function __construct(
        private readonly AuditRecorder $audit,
    ) {}

    public function close(User $user, ?string $reason = null): void
    {
        $this->audit->record(
            event: AuditEvent::USER_CLOSED,
            subject: $user,
            before: ['status' => $user->status->value],
            after: ['status' => UserStatus::Closed->value],
            context: $reason === null ? [] : ['reason' => $reason],
            actor: $user,
        );

        DB::transaction(function () use ($user): void {
            $user->tokens()->delete();

            $user->status = UserStatus::Closed;
            $user->save();

            // Seller-side state is closed too, releasing the public handle.
            $user->sellerProfile()->first()?->delete();

            $user->delete();
        });
    }
}
