<?php

namespace Tests\Unit\Services;

use App\Events\Packages\EventPackageGuestLimitReached;
use App\Events\Packages\EventPackageGuestThresholdReached;
use App\Events\Packages\EventPackagePhotoLimitReached;
use App\Events\Packages\EventPackagePhotoThresholdReached;
use App\Models\Event;
use App\Models\EventPackage;
use App\Models\Package;
use App\Models\Tenant;
use App\Services\Packages\PackageUsageTracker;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Event as EventFacade;
use Tests\TestCase;

class PackageUsageTrackerTest extends TestCase
{
    use RefreshDatabase;

    public function test_dispatches_threshold_event_when_crossed(): void
    {
        EventFacade::fake([
            EventPackagePhotoThresholdReached::class,
            EventPackagePhotoLimitReached::class,
        ]);

        $tenant = Tenant::factory()->create();
        $package = Package::factory()->endcustomer()->create([
            'max_photos' => 10,
        ]);
        $event = Event::factory()->for($tenant)->create();

        $eventPackage = EventPackage::create([
            'event_id' => $event->id,
            'package_id' => $package->id,
            'purchased_price' => $package->price,
            'purchased_at' => now(),
            'used_photos' => 8,
            'used_guests' => 0,
            'gallery_expires_at' => now()->addDays(7),
        ])->fresh(['package']);

        /** @var PackageUsageTracker $tracker */
        $tracker = app(PackageUsageTracker::class);

        $tracker->recordPhotoUsage($eventPackage, 7, 1);

        EventFacade::assertDispatched(EventPackagePhotoThresholdReached::class);
        EventFacade::assertNotDispatched(EventPackagePhotoLimitReached::class);
    }

    public function test_dispatches_limit_event_when_reached(): void
    {
        EventFacade::fake([
            EventPackagePhotoThresholdReached::class,
            EventPackagePhotoLimitReached::class,
        ]);

        $tenant = Tenant::factory()->create();
        $package = Package::factory()->endcustomer()->create([
            'max_photos' => 2,
            'max_guests' => null,
        ]);
        $event = Event::factory()->for($tenant)->create();

        $eventPackage = EventPackage::create([
            'event_id' => $event->id,
            'package_id' => $package->id,
            'purchased_price' => $package->price,
            'purchased_at' => now(),
            'used_photos' => 2,
            'used_guests' => 0,
            'gallery_expires_at' => now()->addDays(7),
        ])->fresh(['package']);

        /** @var PackageUsageTracker $tracker */
        $tracker = app(PackageUsageTracker::class);

        $tracker->recordPhotoUsage($eventPackage, 1, 1);

        EventFacade::assertDispatched(EventPackagePhotoLimitReached::class);
    }

    public function test_dispatches_guest_threshold_event_when_crossed(): void
    {
        EventFacade::fake([
            EventPackageGuestThresholdReached::class,
            EventPackageGuestLimitReached::class,
        ]);

        $tenant = Tenant::factory()->create();
        $package = Package::factory()->endcustomer()->create([
            'max_guests' => 10,
        ]);
        $event = Event::factory()->for($tenant)->create();

        $eventPackage = EventPackage::create([
            'event_id' => $event->id,
            'package_id' => $package->id,
            'purchased_price' => $package->price,
            'purchased_at' => now(),
            'used_photos' => 0,
            'used_guests' => 8,
            'gallery_expires_at' => now()->addDays(7),
        ])->fresh(['package']);

        /** @var PackageUsageTracker $tracker */
        $tracker = app(PackageUsageTracker::class);

        $tracker->recordGuestUsage($eventPackage, 7, 1);

        EventFacade::assertDispatched(EventPackageGuestThresholdReached::class);
        EventFacade::assertNotDispatched(EventPackageGuestLimitReached::class);
    }

    public function test_dispatches_guest_limit_event_when_reached(): void
    {
        EventFacade::fake([
            EventPackageGuestThresholdReached::class,
            EventPackageGuestLimitReached::class,
        ]);

        $tenant = Tenant::factory()->create();
        $package = Package::factory()->endcustomer()->create([
            'max_guests' => 2,
        ]);
        $event = Event::factory()->for($tenant)->create();

        $eventPackage = EventPackage::create([
            'event_id' => $event->id,
            'package_id' => $package->id,
            'purchased_price' => $package->price,
            'purchased_at' => now(),
            'used_photos' => 0,
            'used_guests' => 2,
            'gallery_expires_at' => now()->addDays(7),
        ])->fresh(['package']);

        /** @var PackageUsageTracker $tracker */
        $tracker = app(PackageUsageTracker::class);

        $tracker->recordGuestUsage($eventPackage, 1, 1);

        EventFacade::assertDispatched(EventPackageGuestLimitReached::class);
    }

    public function test_effective_limits_include_extras(): void
    {
        EventFacade::fake([
            EventPackagePhotoLimitReached::class,
        ]);

        $tenant = Tenant::factory()->create();
        $package = Package::factory()->endcustomer()->create([
            'max_photos' => 2,
        ]);
        $event = Event::factory()->for($tenant)->create();

        $eventPackage = EventPackage::create([
            'event_id' => $event->id,
            'package_id' => $package->id,
            'purchased_price' => $package->price,
            'purchased_at' => now(),
            'used_photos' => 2,
            'used_guests' => 0,
            'gallery_expires_at' => now()->addDays(7),
            'extra_photos' => 2,
        ])->fresh(['package']);

        /** @var PackageUsageTracker $tracker */
        $tracker = app(PackageUsageTracker::class);

        // Base limit reached but extras still available; no limit event expected yet.
        $tracker->recordPhotoUsage($eventPackage, 1, 1);
        EventFacade::assertNotDispatched(EventPackagePhotoLimitReached::class);

        // Now consume extras and hit the effective limit.
        $eventPackage->used_photos = 4;
        $tracker->recordPhotoUsage($eventPackage, 3, 1);

        EventFacade::assertDispatched(EventPackagePhotoLimitReached::class);
    }
}
