<?php

declare(strict_types=1);

use App\Models\AuditLog;
use App\Models\BackupItem;
use App\Models\BackupSchedule;
use App\Models\BackupSet;
use App\Models\OperationRun;
use App\Models\Policy;
use App\Models\PolicyVersion;
use App\Models\RestoreRun;
use App\Models\SettingsCatalogCategory;
use App\Models\SettingsCatalogDefinition;
use App\Models\ManagedEnvironment;
use App\Models\User;
use Illuminate\Foundation\Testing\RefreshDatabase;

uses(RefreshDatabase::class);

it('purges non-persistent tenant data while preserving durable audit history', function (): void {
    $tenantA = ManagedEnvironment::factory()->create(['name' => 'ManagedEnvironment A']);
    $tenantB = ManagedEnvironment::factory()->create(['name' => 'ManagedEnvironment B']);

    SettingsCatalogCategory::create([
        'category_id' => 'cat-1',
        'display_name' => 'Account Management',
        'description' => null,
    ]);

    SettingsCatalogDefinition::create([
        'definition_id' => 'def-1',
        'display_name' => 'Deletion Policy',
        'description' => null,
        'help_text' => null,
        'category_id' => 'cat-1',
        'ux_behavior' => null,
        'raw' => [],
    ]);

    $user = User::factory()->create();

    $policyA = Policy::factory()->create(['managed_environment_id' => $tenantA->id]);
    $policyB = Policy::factory()->create(['managed_environment_id' => $tenantB->id]);

    PolicyVersion::factory()->create([
        'managed_environment_id' => $tenantA->id,
        'policy_id' => $policyA->id,
        'version_number' => 1,
    ]);

    PolicyVersion::factory()->create([
        'managed_environment_id' => $tenantB->id,
        'policy_id' => $policyB->id,
        'version_number' => 1,
    ]);

    $backupSetA = BackupSet::factory()->create(['managed_environment_id' => $tenantA->id]);
    BackupItem::factory()->create([
        'managed_environment_id' => $tenantA->id,
        'backup_set_id' => $backupSetA->id,
        'policy_id' => $policyA->id,
    ]);

    RestoreRun::factory()->create([
        'managed_environment_id' => $tenantA->id,
        'backup_set_id' => $backupSetA->id,
    ]);

    AuditLog::create([
        'managed_environment_id' => $tenantA->id,
        'actor_id' => null,
        'actor_email' => null,
        'actor_name' => null,
        'action' => 'test.action',
        'resource_type' => null,
        'resource_id' => null,
        'status' => 'success',
        'metadata' => null,
        'recorded_at' => now(),
    ]);

    OperationRun::factory()->create([
        'managed_environment_id' => $tenantA->id,
        'user_id' => $user->id,
        'status' => 'completed',
    ]);

    $scheduleA = BackupSchedule::create([
        'managed_environment_id' => $tenantA->id,
        'name' => 'Schedule A',
        'is_enabled' => true,
        'timezone' => 'UTC',
        'frequency' => 'daily',
        'time_of_day' => '10:00:00',
        'days_of_week' => null,
        'policy_types' => ['deviceConfiguration'],
        'include_foundations' => true,
        'retention_keep_last' => 30,
        'last_run_at' => null,
        'last_run_status' => null,
        'next_run_at' => now()->addHour(),
    ]);

    expect(Policy::query()->where('managed_environment_id', $tenantA->id)->count())->toBeGreaterThan(0);
    expect(BackupSet::withTrashed()->where('managed_environment_id', $tenantA->id)->count())->toBeGreaterThan(0);
    expect(OperationRun::query()->where('managed_environment_id', $tenantA->id)->count())->toBeGreaterThan(0);

    $this->artisan('tenantpilot:purge-nonpersistent', [
        'tenant' => $tenantA->id,
        '--force' => true,
        '--no-interaction' => true,
    ])->assertSuccessful();

    expect(Policy::query()->where('managed_environment_id', $tenantA->id)->count())->toBe(0);
    expect(PolicyVersion::withTrashed()->where('managed_environment_id', $tenantA->id)->count())->toBe(0);
    expect(BackupItem::withTrashed()->where('managed_environment_id', $tenantA->id)->count())->toBe(0);
    expect(BackupSet::withTrashed()->where('managed_environment_id', $tenantA->id)->count())->toBe(0);
    expect(RestoreRun::withTrashed()->where('managed_environment_id', $tenantA->id)->count())->toBe(0);
    expect(AuditLog::query()->where('managed_environment_id', $tenantA->id)->count())->toBe(2);
    expect(AuditLog::query()
        ->where('managed_environment_id', $tenantA->id)
        ->orderBy('action')
        ->pluck('action')
        ->all())->toBe([
            'operation.completed',
            'test.action',
        ]);
    expect(OperationRun::query()->where('managed_environment_id', $tenantA->id)->count())->toBe(1);
    expect(OperationRun::query()
        ->where('managed_environment_id', $tenantA->id)
        ->where('type', 'backup.schedule.purge')
        ->exists())->toBeTrue();

    $purgeRun = OperationRun::query()
        ->where('managed_environment_id', $tenantA->id)
        ->where('type', 'backup.schedule.purge')
        ->latest('id')
        ->first();

    expect($purgeRun)->not->toBeNull();
    expect(data_get($purgeRun?->context, 'audit_logs_retained'))->toBe(2)
        ->and(data_get($purgeRun?->context, 'deleted_rows.audit_logs_retained'))->toBeNull();

    expect(BackupSchedule::query()->where('managed_environment_id', $tenantA->id)->count())->toBe(0);

    expect(Policy::query()->where('managed_environment_id', $tenantB->id)->count())->toBe(1);
    expect(PolicyVersion::withTrashed()->where('managed_environment_id', $tenantB->id)->count())->toBe(1);

    expect(SettingsCatalogCategory::query()->count())->toBe(1);
    expect(SettingsCatalogDefinition::query()->count())->toBe(1);
});
