<?php

namespace Tests\Unit;

use App\Events\Packages\TenantPackageEventLimitReached;
use App\Events\Packages\TenantPackageEventThresholdReached;
use App\Models\Event;
use App\Models\Package;
use App\Models\PackagePurchase;
use App\Models\Photo;
use App\Models\Tenant;
use App\Models\TenantPackage;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Config;
use Illuminate\Support\Facades\Event as EventFacade;
use Tests\TestCase;

class TenantModelTest extends TestCase
{
    use RefreshDatabase;

    public function test_tenant_has_many_events(): void
    {
        $tenant = Tenant::factory()->create();
        Event::factory()->count(3)->create(['tenant_id' => $tenant->id]);

        $this->assertCount(3, $tenant->events()->get());
    }

    public function test_tenant_has_photos_through_events(): void
    {
        $tenant = Tenant::factory()->create();
        $event = Event::factory()->create(['tenant_id' => $tenant->id]);
        Photo::factory()->count(2)->create(['event_id' => $event->id]);

        $this->assertCount(2, $tenant->photos()->get());
    }

    public function test_tenant_has_many_package_purchases(): void
    {
        $tenant = Tenant::factory()->create();
        $package = Package::factory()->create();
        PackagePurchase::factory()->count(2)->create([
            'tenant_id' => $tenant->id,
            'package_id' => $package->id,
        ]);

        $this->assertCount(2, $tenant->purchases()->get());
    }

    public function test_active_subscription_accessor_returns_true_when_active_package_exists(): void
    {
        $tenant = Tenant::factory()->create();
        $package = Package::factory()->create(['type' => 'reseller']);

        TenantPackage::factory()->create([
            'tenant_id' => $tenant->id,
            'package_id' => $package->id,
            'active' => true,
        ]);

        $this->assertTrue($tenant->fresh()->active_subscription);
    }

    public function test_active_subscription_accessor_returns_false_without_active_package(): void
    {
        $tenant = Tenant::factory()->create();

        $this->assertFalse($tenant->fresh()->active_subscription);
    }

    public function test_increment_used_events_returns_false_without_active_package(): void
    {
        $tenant = Tenant::factory()->create();

        $this->assertFalse($tenant->incrementUsedEvents());
    }

    public function test_increment_used_events_updates_active_package(): void
    {
        $tenant = Tenant::factory()->create();
        $package = Package::factory()->create(['type' => 'reseller']);
        $tenantPackage = TenantPackage::factory()->create([
            'tenant_id' => $tenant->id,
            'package_id' => $package->id,
            'active' => true,
            'used_events' => 1,
        ]);

        $this->assertTrue($tenant->incrementUsedEvents(2));
        $this->assertEquals(3, $tenantPackage->fresh()->used_events);
    }

    public function test_consume_event_allowance_dispatches_notifications_and_updates_usage(): void
    {
        EventFacade::fake([
            TenantPackageEventThresholdReached::class,
            TenantPackageEventLimitReached::class,
        ]);

        Config::set('package-limits.event_thresholds', [0.5]);

        $tenant = Tenant::factory()->create();
        $package = Package::factory()->create([
            'type' => 'reseller',
            'max_events_per_year' => 4,
        ]);

        $tenantPackage = TenantPackage::factory()->create([
            'tenant_id' => $tenant->id,
            'package_id' => $package->id,
            'active' => true,
            'used_events' => 1,
        ]);

        $this->assertTrue($tenant->consumeEventAllowance());

        EventFacade::assertDispatched(TenantPackageEventThresholdReached::class);
        EventFacade::assertNotDispatched(TenantPackageEventLimitReached::class);

        $tenantPackage->refresh();

        $this->assertSame(2, $tenantPackage->used_events);
        $this->assertNotNull($tenantPackage->event_warning_sent_at);
        $this->assertSame(0.5, (float) $tenantPackage->event_warning_threshold);
    }

    public function test_settings_cast_to_array(): void
    {
        $tenant = Tenant::factory()->create([
            'settings' => ['theme' => 'dark', 'logo' => 'logo.png'],
        ]);

        $this->assertIsArray($tenant->settings);
        $this->assertSame('dark', $tenant->settings['theme']);
    }

    public function test_features_cast_to_array(): void
    {
        $tenant = Tenant::factory()->create([
            'features' => ['photo_likes' => true, 'analytics' => false],
        ]);

        $this->assertIsArray($tenant->features);
        $this->assertTrue($tenant->features['photo_likes']);
        $this->assertFalse($tenant->features['analytics']);
    }

    public function test_consume_event_allowance_moves_to_next_credit_batch(): void
    {
        $tenant = Tenant::factory()->create();

        $firstPackage = Package::factory()->reseller()->create([
            'max_events_per_year' => 1,
        ]);

        $secondPackage = Package::factory()->reseller()->create([
            'max_events_per_year' => 1,
        ]);

        $firstBatch = TenantPackage::factory()->for($tenant)->for($firstPackage)->create([
            'used_events' => 0,
            'active' => true,
            'expires_at' => null,
            'purchased_at' => now()->subDay(),
        ]);

        $secondBatch = TenantPackage::factory()->for($tenant)->for($secondPackage)->create([
            'used_events' => 0,
            'active' => true,
            'expires_at' => null,
            'purchased_at' => now(),
        ]);

        $this->assertTrue($tenant->consumeEventAllowance());
        $this->assertFalse($firstBatch->fresh()->active);
        $this->assertTrue($secondBatch->fresh()->active);

        $this->assertTrue($tenant->consumeEventAllowance());
        $this->assertFalse($secondBatch->fresh()->active);

        $this->assertFalse($tenant->consumeEventAllowance());
    }
}
