<?php

namespace App\Actions\Events;

use App\Enums\PaymentStatus;
use App\Enums\PricingType;
use App\Enums\RegistrationStatus;
use App\Events\RegistrationStatusChanged;
use App\Models\EventRegistration;
use App\Models\User;
use App\Services\AuditLogger;
use App\Services\RegistrationStatusService;
use Illuminate\Support\Facades\DB;
use InvalidArgumentException;

class PromoteWaitlistAction
{
    public function __construct(
        private RegistrationStatusService $registrationStatus,
        private AuditLogger $auditLogger,
    ) {}

    public function execute(EventRegistration $registration, User $admin, ?string $reason = null): EventRegistration
    {
        return DB::transaction(function () use ($registration, $admin, $reason) {
            if ($registration->status !== RegistrationStatus::Waitlisted) {
                throw new InvalidArgumentException(__('events.errors.invalid_status'));
            }

            if (! $this->registrationStatus->hasCapacity($registration->event)) {
                throw new InvalidArgumentException(__('events.registration.capacity_full'));
            }

            $newStatus = $registration->event->pricing_type === PricingType::Paid
                ? RegistrationStatus::PendingPayment
                : RegistrationStatus::Confirmed;

            $paymentStatus = $registration->event->pricing_type === PricingType::Paid
                ? PaymentStatus::Pending
                : PaymentStatus::NotRequired;

            $oldStatus = $registration->status;

            $this->registrationStatus->record(
                $registration,
                $newStatus,
                $oldStatus,
                $admin,
                $reason ?? 'Promoted from waitlist',
            );

            $registration->update([
                'waitlist_position' => null,
                'payment_status' => $paymentStatus,
                'confirmed_at' => $newStatus === RegistrationStatus::Confirmed ? now() : null,
                'reviewed_by' => $admin->id,
                'reviewed_at' => now(),
            ]);

            $this->auditLogger->log('registration.promoted', $registration, ['status' => $oldStatus->value], ['status' => $newStatus->value]);

            event(new RegistrationStatusChanged(
                registration: $registration->fresh(['event', 'user']),
                previousStatus: $oldStatus,
                wasPromotedFromWaitlist: true,
            ));

            return $registration->fresh(['event', 'user']);
        });
    }
}
