<?php

namespace App\Services;

use App\Enums\RegistrationStatus;
use App\Models\Event;
use App\Models\EventRegistration;
use App\Models\EventRegistrationStatusEvent;
use App\Models\User;

class RegistrationStatusService
{
    /** @var list<RegistrationStatus> */
    public const CAPACITY_HOLDING_STATUSES = [
        RegistrationStatus::Pending,
        RegistrationStatus::PendingPayment,
        RegistrationStatus::PaymentReview,
        RegistrationStatus::Confirmed,
        RegistrationStatus::CheckedIn,
        RegistrationStatus::Attended,
    ];

    public function record(
        EventRegistration $registration,
        RegistrationStatus $newStatus,
        ?RegistrationStatus $oldStatus = null,
        ?User $changedBy = null,
        ?string $reason = null,
    ): EventRegistrationStatusEvent {
        $old = $oldStatus ?? $registration->status;

        EventRegistrationStatusEvent::query()->create([
            'event_registration_id' => $registration->id,
            'old_status' => $old,
            'new_status' => $newStatus,
            'changed_by' => $changedBy?->id ?? auth()->id(),
            'reason' => $reason,
        ]);

        $registration->update(['status' => $newStatus]);

        return $registration->statusEvents()->latest('id')->first();
    }

    public function occupiedCount(Event $event): int
    {
        return $event->registrations()
            ->whereIn('status', self::CAPACITY_HOLDING_STATUSES)
            ->count();
    }

    public function hasCapacity(Event $event): bool
    {
        if ($event->capacity === null) {
            return true;
        }

        return $this->occupiedCount($event) < $event->capacity;
    }

    public function nextWaitlistPosition(Event $event): int
    {
        $max = $event->registrations()
            ->where('status', RegistrationStatus::Waitlisted)
            ->max('waitlist_position');

        return ((int) $max) + 1;
    }

    public function hasActiveRegistration(Event $event, User $user): bool
    {
        return $event->registrations()
            ->where('user_id', $user->id)
            ->whereIn('status', array_map(
                fn (RegistrationStatus $status) => $status->value,
                array_filter(
                    RegistrationStatus::cases(),
                    fn (RegistrationStatus $status) => $status->isActive(),
                ),
            ))
            ->exists();
    }
}
