<?php

it('defines durable backup schema tables for records, components, jobs, and restore audit', function (): void {
    $content = file_get_contents(app_path('classes/backup_schema_bootstrap.php'));

    expect($content)->toContain('CREATE TABLE IF NOT EXISTS backup_records')
        ->and($content)->toContain('CREATE TABLE IF NOT EXISTS backup_components')
        ->and($content)->toContain('CREATE TABLE IF NOT EXISTS backup_jobs')
        ->and($content)->toContain('CREATE TABLE IF NOT EXISTS backup_restore_audit')
        ->and($content)->toContain('manifest_sha256')
        ->and($content)->toContain('encryption_key_id');
});

it('hardens database dumps by keeping passwords out of the mysqldump command', function (): void {
    $content = file_get_contents(app_path('classes/db.php'));

    expect($content)->toContain('MYSQL_PWD')
        ->and($content)->toContain('--single-transaction')
        ->and($content)->toContain('--routines')
        ->and($content)->toContain('--triggers')
        ->and($content)->toContain('--events')
        ->and($content)->not->toContain('--password=$pass');
});

it('uses encrypted component backups and never stores raw environment dumps', function (): void {
    $content = file_get_contents(app_path('classes/backup_store.php'));

    expect($content)->toContain('AES-256-GCM')
        ->and($content)->toContain('BACKUP_ENCRYPTION_KEY_V1')
        ->and($content)->toContain('required_runtime_config_keys')
        ->and($content)->toContain('createObjectBucketComponent')
        ->and($content)->not->toContain('json_encode($_ENV)')
        ->and($content)->not->toContain("exec('zip -r");
});

it('normalizes string boolean config values before destructive restore gates', function (): void {
    $content = file_get_contents(app_path('classes/backup_store.php'));

    expect($content)->toContain("['1', 'true', 'yes', 'on']")
        ->and($content)->toContain("['0', 'false', 'no', 'off', '']")
        ->and($content)->toContain('Backup system is disabled in backup configuration.')
        ->and($content)->toContain('Direct production restore is disabled in backup configuration.');
});

it('wires backup job, verification, restore preview, restore, and audit routes', function (): void {
    $content = file_get_contents(app_path('routes/moduleBackupsRoute.php'));

    expect($content)->toContain('/modules/backup/jobs/{id}')
        ->and($content)->toContain('/modules/backup/backups/{backup_uuid}/verify')
        ->and($content)->toContain('/modules/backup/backups/{backup_uuid}/restore/preview')
        ->and($content)->toContain('/modules/backup/backups/{backup_uuid}/restore')
        ->and($content)->toContain('/modules/backup/restore-audit')
        ->and($content)->toContain('modules_backup_restore')
        ->and($content)->toContain('Subuser sessions cannot manage backup disaster recovery.');
});

it('registers hourly backup enqueue, worker, and retention prune cron tasks', function (): void {
    $content = file_get_contents(app_path('modules/backups/cron/tasks.php'));
    $cron = file_get_contents(app_path('cron/Cron.php'));

    expect($content)->toContain("'seconds' => 3600")
        ->and($content)->toContain('backups.process_jobs')
        ->and($content)->toContain('backups.prune_retention')
        ->and($cron)->toContain('processBackupJobs')
        ->and($cron)->toContain('pruneBackupRetention');
});

it('documents backup disaster recovery APIs and config variables in openapi', function (): void {
    $content = file_get_contents(app_path('openapi.yaml'));

    expect($content)->toContain('/modules/backup/jobs/{id}:')
        ->and($content)->toContain('/modules/backup/backups/{backup_uuid}/restore/preview:')
        ->and($content)->toContain('BackupRestoreRequest')
        ->and($content)->toContain('BackupRestoreAuditListResponse')
        ->and($content)->toContain('retention_recent_hours')
        ->and($content)->toContain('verification_required')
        ->and($content)->toContain('restore_enabled');
});
