<?php

namespace App\Console\Commands;

use App\Events\Packages\EventPackageGalleryExpired;
use App\Events\Packages\EventPackageGalleryExpiring;
use App\Models\EventPackage;
use App\Services\Monitoring\PackageLimitMetrics;
use Illuminate\Console\Command;

class CheckEventPackages extends Command
{
    protected $signature = 'package:check-status';

    protected $description = 'Check event packages for upcoming gallery expiry and emit notifications.';

    public function handle(): int
    {
        $warningDays = collect(config('package-limits.gallery_warning_days', []))
            ->filter(fn ($day) => is_numeric($day) && $day > 0)
            ->map(fn ($day) => (int) $day)
            ->unique()
            ->sortDesc() // handle larger days first
            ->values();

        $eventPackageExpiryDays = collect(config('package-limits.package_expiry_days', []))
            ->filter(fn ($day) => is_numeric($day) && $day > 0)
            ->map(fn ($day) => (int) $day)
            ->unique()
            ->sortDesc()
            ->values();

        $now = now();

        EventPackage::query()
            ->whereNotNull('gallery_expires_at')
            ->chunkById(100, function ($packages) use ($warningDays, $now) {
                foreach ($packages as $package) {
                    $expiresAt = $package->gallery_expires_at;
                    if (! $expiresAt) {
                        continue;
                    }

                    $daysDiff = $now->diffInDays($expiresAt, false);

                    if ($warningDays->isNotEmpty() && $package->gallery_warning_sent_at) {
                        $maxWarningDay = $warningDays->max();
                        if ($maxWarningDay !== null && $daysDiff > $maxWarningDay) {
                            $package->forceFill([
                                'gallery_warning_sent_at' => null,
                            ])->save();
                        }
                    }

                    if ($daysDiff < 0) {
                        if (! $package->gallery_expired_notified_at) {
                            event(new EventPackageGalleryExpired($package));
                            PackageLimitMetrics::recordGalleryExpired();
                            $package->forceFill([
                                'gallery_expired_notified_at' => $now,
                            ])->save();
                        }

                        continue;
                    }

                    if ($warningDays->isEmpty()) {
                        continue;
                    }

                    if ($package->gallery_warning_sent_at) {
                        continue;
                    }

                    foreach ($warningDays as $day) {
                        if ($daysDiff <= $day && $daysDiff >= 0) {
                            event(new EventPackageGalleryExpiring($package, $day));
                            PackageLimitMetrics::recordGalleryWarning($day);
                            $package->forceFill([
                                'gallery_warning_sent_at' => $now,
                            ])->save();
                            break;
                        }
                    }
                }
            });

        \App\Models\TenantPackage::query()
            ->with(['tenant', 'package'])
            ->whereNotNull('expires_at')
            ->chunkById(100, function ($tenantPackages) use ($eventPackageExpiryDays, $now) {
                foreach ($tenantPackages as $tenantPackage) {
                    $expiresAt = $tenantPackage->expires_at;
                    if (! $expiresAt) {
                        continue;
                    }

                    $daysDiff = $now->diffInDays($expiresAt, false);

                    if ($daysDiff < 0) {
                        if (! $tenantPackage->expired_notified_at) {
                            event(new \App\Events\Packages\TenantPackageExpired($tenantPackage));
                            PackageLimitMetrics::recordTenantPackageExpired();
                            $tenantPackage->forceFill(['expired_notified_at' => $now])->save();
                        }

                        continue;
                    }

                    if ($eventPackageExpiryDays->isNotEmpty() && $tenantPackage->expiry_warning_sent_at) {
                        $maxTenantWarning = $eventPackageExpiryDays->max();
                        if ($maxTenantWarning !== null && $daysDiff > $maxTenantWarning) {
                            $tenantPackage->forceFill(['expiry_warning_sent_at' => null])->save();
                        } else {
                            continue;
                        }
                    } elseif ($tenantPackage->expiry_warning_sent_at) {
                        $tenantPackage->forceFill(['expiry_warning_sent_at' => null])->save();
                    }

                    foreach ($eventPackageExpiryDays as $day) {
                        if ($daysDiff <= $day && $daysDiff >= 0) {
                            event(new \App\Events\Packages\TenantPackageExpiring($tenantPackage, $day));
                            PackageLimitMetrics::recordTenantPackageWarning($day);
                            $tenantPackage->forceFill(['expiry_warning_sent_at' => $now])->save();
                            break;
                        }
                    }
                }
            });

        return self::SUCCESS;
    }
}
