<?php

namespace App\Services\Packages;

use App\Events\Packages\TenantPackageEventLimitReached;
use App\Events\Packages\TenantPackageEventThresholdReached;
use App\Models\TenantPackage;
use Illuminate\Contracts\Events\Dispatcher;

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

    public function recordEventUsage(TenantPackage $tenantPackage, int $previousUsed, int $delta = 1): void
    {
        $limit = $tenantPackage->package?->max_events_per_year;

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

        $newUsed = (int) $tenantPackage->used_events;

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

        if ($limit > 0) {
            $previousRatio = $previousUsed / $limit;
            $newRatio = $newUsed / $limit;
            $currentThreshold = $tenantPackage->event_warning_threshold ?? null;

            foreach ($thresholds as $threshold) {
                if ($previousRatio < $threshold && $newRatio >= $threshold) {
                    if ($currentThreshold !== null && $currentThreshold >= $threshold) {
                        continue;
                    }

                    $tenantPackage->forceFill([
                        'event_warning_sent_at' => now(),
                        'event_warning_threshold' => $threshold,
                    ])->save();

                    $this->dispatcher->dispatch(new TenantPackageEventThresholdReached(
                        $tenantPackage,
                        $threshold,
                        $limit,
                        $newUsed,
                    ));

                    $currentThreshold = $threshold;
                }
            }
        }

        if ($newUsed >= $limit && $previousUsed < $limit) {
            if (! $tenantPackage->event_limit_notified_at) {
                $tenantPackage->forceFill([
                    'event_limit_notified_at' => now(),
                ])->save();
            }

            $this->dispatcher->dispatch(new TenantPackageEventLimitReached($tenantPackage, $limit));

            if ($tenantPackage->active) {
                $tenantPackage->forceFill([
                    'active' => false,
                ])->save();
            }
        }
    }
}
