<?php

namespace App\Services\Packages;

use App\Events\Packages\EventPackageGuestLimitReached;
use App\Events\Packages\EventPackageGuestThresholdReached;
use App\Events\Packages\EventPackagePhotoLimitReached;
use App\Events\Packages\EventPackagePhotoThresholdReached;
use App\Models\EventPackage;
use Illuminate\Contracts\Events\Dispatcher;

class PackageUsageTracker
{
    public function __construct(private readonly Dispatcher $dispatcher) {}

    public function recordPhotoUsage(EventPackage $eventPackage, int $previousUsed, int $delta = 1): void
    {
        $limit = $eventPackage->effectivePhotoLimit();

        if ($limit === null || $limit <= 0) {
            return;
        }

        $newUsed = $eventPackage->used_photos;

        $thresholds = collect(config('package-limits.photo_thresholds', []))
            ->filter(fn (float $value) => $value > 0 && $value < 1)
            ->sort()
            ->values();

        if ($limit > 0) {
            $previousRatio = $previousUsed / $limit;
            $newRatio = $newUsed / $limit;

            foreach ($thresholds as $threshold) {
                if ($previousRatio < $threshold && $newRatio >= $threshold) {
                    $this->dispatcher->dispatch(new EventPackagePhotoThresholdReached(
                        $eventPackage,
                        $threshold,
                        $limit,
                        $newUsed,
                    ));
                }
            }
        }

        if ($newUsed >= $limit && ($previousUsed < $limit)) {
            $this->dispatcher->dispatch(new EventPackagePhotoLimitReached($eventPackage, $limit));
        }
    }

    public function recordGuestUsage(EventPackage $eventPackage, int $previousUsed, int $delta = 1): void
    {
        $limit = $eventPackage->effectiveGuestLimit();

        if ($limit === null || $limit <= 0) {
            return;
        }

        $newUsed = $eventPackage->used_guests;

        $thresholds = collect(config('package-limits.guest_thresholds', []))
            ->filter(fn (float $value) => $value > 0 && $value < 1)
            ->sort()
            ->values();

        if ($limit > 0) {
            $previousRatio = $previousUsed / $limit;
            $newRatio = $newUsed / $limit;

            foreach ($thresholds as $threshold) {
                if ($previousRatio < $threshold && $newRatio >= $threshold) {
                    $this->dispatcher->dispatch(new EventPackageGuestThresholdReached(
                        $eventPackage,
                        $threshold,
                        $limit,
                        $newUsed,
                    ));
                }
            }
        }

        if ($newUsed >= $limit && ($previousUsed < $limit)) {
            $this->dispatcher->dispatch(new EventPackageGuestLimitReached($eventPackage, $limit));
        }
    }
}
