<?php

namespace Tests\Feature;

use App\Filament\Resources\TenantResource\Pages\ListTenants;
use App\Jobs\AnonymizeAccount;
use App\Models\SuperAdminActionLog;
use App\Models\Tenant;
use App\Models\TenantLifecycleEvent;
use App\Models\User;
use Filament\Actions\Testing\TestAction;
use Filament\Facades\Filament;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Illuminate\Support\Facades\Notification;
use Illuminate\Support\Facades\Queue;
use Livewire\Livewire;
use Tests\TestCase;

class TenantLifecycleActionsTest extends TestCase
{
    use RefreshDatabase;

    public function test_superadmin_can_schedule_and_cancel_tenant_deletion(): void
    {
        Notification::fake();

        $user = User::factory()->create(['role' => 'super_admin']);
        $tenant = Tenant::factory()->create();

        $this->bootSuperAdminPanel($user);

        $plannedDeletion = now()->addWeeks(2);

        Livewire::test(ListTenants::class)
            ->callAction(
                TestAction::make('schedule_deletion')->table($tenant),
                [
                    'pending_deletion_at' => $plannedDeletion->toDateTimeString(),
                    'send_warning' => false,
                ]
            );

        $tenant->refresh();

        $this->assertNotNull($tenant->pending_deletion_at);
        $this->assertSame(
            $plannedDeletion->toDateTimeString(),
            $tenant->pending_deletion_at?->toDateTimeString()
        );
        $this->assertTrue(TenantLifecycleEvent::query()
            ->where('tenant_id', $tenant->id)
            ->where('type', 'deletion_scheduled')
            ->exists());

        Livewire::test(ListTenants::class)
            ->callAction(TestAction::make('cancel_deletion')->table($tenant));

        $tenant->refresh();

        $this->assertNull($tenant->pending_deletion_at);
        $this->assertNull($tenant->deletion_warning_sent_at);
        $this->assertTrue(TenantLifecycleEvent::query()
            ->where('tenant_id', $tenant->id)
            ->where('type', 'deletion_cancelled')
            ->exists());
    }

    public function test_superadmin_can_toggle_tenant_status_flags(): void
    {
        $user = User::factory()->create(['role' => 'super_admin']);
        $tenant = Tenant::factory()->create([
            'is_active' => true,
            'is_suspended' => false,
        ]);

        $this->bootSuperAdminPanel($user);

        Livewire::test(ListTenants::class)
            ->callAction(TestAction::make('deactivate')->table($tenant));

        $tenant->refresh();
        $this->assertFalse((bool) $tenant->is_active);
        $this->assertTrue(SuperAdminActionLog::query()
            ->where('action', 'tenant.deactivated')
            ->where('subject_id', $tenant->id)
            ->exists());
        $this->assertTrue(TenantLifecycleEvent::query()
            ->where('tenant_id', $tenant->id)
            ->where('type', 'deactivated')
            ->exists());

        Livewire::test(ListTenants::class)
            ->callAction(TestAction::make('activate')->table($tenant));

        $tenant->refresh();
        $this->assertTrue((bool) $tenant->is_active);
        $this->assertTrue(TenantLifecycleEvent::query()
            ->where('tenant_id', $tenant->id)
            ->where('type', 'activated')
            ->exists());

        Livewire::test(ListTenants::class)
            ->callAction(TestAction::make('suspend')->table($tenant));

        $tenant->refresh();
        $this->assertTrue((bool) $tenant->is_suspended);
        $this->assertTrue(TenantLifecycleEvent::query()
            ->where('tenant_id', $tenant->id)
            ->where('type', 'suspended')
            ->exists());

        Livewire::test(ListTenants::class)
            ->callAction(TestAction::make('unsuspend')->table($tenant));

        $tenant->refresh();
        $this->assertFalse((bool) $tenant->is_suspended);
        $this->assertTrue(TenantLifecycleEvent::query()
            ->where('tenant_id', $tenant->id)
            ->where('type', 'unsuspended')
            ->exists());
    }

    public function test_superadmin_can_dispatch_tenant_anonymization(): void
    {
        Queue::fake();

        $user = User::factory()->create(['role' => 'super_admin']);
        $tenant = Tenant::factory()->create();

        $this->bootSuperAdminPanel($user);

        Livewire::test(ListTenants::class)
            ->callAction(TestAction::make('anonymize_now')->table($tenant));

        Queue::assertPushed(AnonymizeAccount::class, function (AnonymizeAccount $job) use ($tenant) {
            return $job->tenantId() === $tenant->id;
        });
        $this->assertTrue(TenantLifecycleEvent::query()
            ->where('tenant_id', $tenant->id)
            ->where('type', 'anonymize_requested')
            ->exists());
    }

    private function bootSuperAdminPanel(User $user): void
    {
        $panel = Filament::getPanel('superadmin');

        $this->assertNotNull($panel);

        Filament::setCurrentPanel($panel);
        Filament::bootCurrentPanel();
        Filament::auth()->login($user);
    }
}
