<?php

declare(strict_types=1);

namespace Tests\Feature;

use App\Features\Auth\Models\AdminSecurityLog;
use App\Features\Auth\Models\User;
use App\Features\Monitoring\Models\VerifiedSafeFile;
use App\Features\Monitoring\Services\VerifiedSafeFileSyncService;
use Illuminate\Foundation\Testing\RefreshDatabase;
use Tests\TestCase;

class VerifiedSafeFileTest extends TestCase
{
    use RefreshDatabase;

    private User $admin;

    protected function setUp(): void
    {
        parent::setUp();

        $this->admin = User::create([
            'name' => 'Verified Safe Admin',
            'email' => 'verified-safe-admin@test.com',
            'password' => bcrypt('password'),
        ]);
    }

    public function test_verify_safe_creates_fingerprint_record(): void
    {
        $this->actingAs($this->admin);

        $agent = \App\Features\Agent\Models\Agent::create([
            'domain' => 'verify-safe.test',
            'site_name' => 'Verify Safe Site',
            'status' => 'active',
            'hmac_secret' => str_repeat('a', 32),
        ]);

        $sha256 = str_repeat('a', 64);
        $report = \App\Features\Monitoring\Models\MalwareReport::create([
            'agent_id' => $agent->id,
            'files_scanned' => 10,
            'malicious_files_found' => 0,
            'threat_details' => [
                'engine_version' => '2.2',
                'files' => [[
                    'path' => 'wp-content/plugins/elementor/vendor/env.php',
                    'type' => 'PHP.Info.Eval',
                    'score' => 45,
                    'classification' => 'suspicious',
                    'status_label' => 'Needs Verification',
                    'plugin_slug' => 'elementor',
                    'plugin_name' => 'Elementor',
                    'plugin_version' => '3.32.5',
                    'relative_path' => 'vendor/env.php',
                    'sha256' => $sha256,
                ]],
            ],
            'scanned_at' => now(),
        ]);

        $response = $this->postJson('/api/v1/verified-safe-files', [
            'malware_report_id' => $report->id,
            'finding_path' => 'wp-content/plugins/elementor/vendor/env.php',
            'plugin_slug' => 'elementor',
            'plugin_name' => 'Elementor',
            'plugin_version' => '3.32.5',
            'relative_path' => 'vendor/env.php',
            'sha256' => $sha256,
            'detection_rule' => 'eval()',
            'status_label' => 'Needs Verification',
            'classification' => 'suspicious',
            'score' => 45,
        ]);

        $response->assertCreated()
            ->assertJsonPath('record.plugin_slug', 'elementor')
            ->assertJsonPath('record.enabled', true);

        $this->assertDatabaseHas('verified_safe_files', [
            'plugin_slug' => 'elementor',
            'plugin_version' => '3.32.5',
            'sha256' => str_repeat('a', 64),
            'enabled' => true,
        ]);

        $this->assertDatabaseHas('admin_security_logs', [
            'event' => 'verified_safe.added',
            'user_id' => $this->admin->id,
        ]);
    }

    public function test_high_score_findings_cannot_be_verified_via_api(): void
    {
        $this->actingAs($this->admin);

        $report = $this->createReportWithFinding([
            'score' => 75,
            'status_label' => 'Needs Verification',
            'classification' => 'suspicious',
            'sha256' => str_repeat('9', 64),
        ]);

        $this->postJson('/api/v1/verified-safe-files', [
            'malware_report_id' => $report->id,
            'finding_path' => 'wp-content/plugins/elementor/vendor/env.php',
            'plugin_slug' => 'elementor',
            'plugin_version' => '3.32.5',
            'relative_path' => 'vendor/env.php',
            'sha256' => str_repeat('9', 64),
            'status_label' => 'Needs Verification',
            'classification' => 'suspicious',
            'score' => 75,
        ])->assertStatus(422);
    }

    public function test_forced_malware_flag_cannot_be_verified_via_api(): void
    {
        $this->actingAs($this->admin);

        $report = $this->createReportWithFinding([
            'forced_malware' => true,
            'status_label' => 'Needs Verification',
            'sha256' => str_repeat('8', 64),
        ]);

        $this->postJson('/api/v1/verified-safe-files', [
            'malware_report_id' => $report->id,
            'finding_path' => 'wp-content/plugins/elementor/vendor/env.php',
            'plugin_slug' => 'elementor',
            'plugin_version' => '3.32.5',
            'relative_path' => 'vendor/env.php',
            'sha256' => str_repeat('8', 64),
            'status_label' => 'Needs Verification',
            'forced_malware' => true,
        ])->assertStatus(422);
    }

    public function test_confirmed_malware_cannot_be_verified(): void
    {
        $this->actingAs($this->admin);

        $report = $this->createReportWithFinding([
            'status_label' => 'Confirmed Malware',
            'classification' => 'malware',
            'score' => 80,
            'sha256' => str_repeat('b', 64),
        ]);

        $this->postJson('/api/v1/verified-safe-files', [
            'malware_report_id' => $report->id,
            'finding_path' => 'wp-content/plugins/elementor/vendor/env.php',
            'plugin_slug' => 'elementor',
            'plugin_version' => '3.32.5',
            'relative_path' => 'vendor/env.php',
            'sha256' => str_repeat('b', 64),
            'status_label' => 'Confirmed Malware',
            'classification' => 'malware',
        ])->assertStatus(422);
    }

    public function test_spoofed_fingerprint_is_rejected(): void
    {
        $this->actingAs($this->admin);

        $report = $this->createReportWithFinding([
            'sha256' => str_repeat('c', 64),
        ]);

        $this->postJson('/api/v1/verified-safe-files', [
            'malware_report_id' => $report->id,
            'finding_path' => 'wp-content/plugins/elementor/vendor/env.php',
            'plugin_slug' => 'elementor',
            'plugin_version' => '3.32.5',
            'relative_path' => 'vendor/env.php',
            'sha256' => str_repeat('d', 64),
            'status_label' => 'Needs Verification',
            'classification' => 'suspicious',
            'score' => 45,
        ])->assertStatus(422);
    }

    public function test_duplicate_fingerprint_is_rejected(): void
    {
        VerifiedSafeFile::create([
            'plugin_slug' => 'elementor',
            'plugin_version' => '3.32.5',
            'relative_path' => 'vendor/file.php',
            'sha256' => str_repeat('c', 64),
            'enabled' => true,
        ]);

        $this->actingAs($this->admin);

        $report = $this->createReportWithFinding([
            'relative_path' => 'vendor/file.php',
            'path' => 'wp-content/plugins/elementor/vendor/file.php',
            'sha256' => str_repeat('c', 64),
        ]);

        $this->postJson('/api/v1/verified-safe-files', [
            'malware_report_id' => $report->id,
            'finding_path' => 'wp-content/plugins/elementor/vendor/file.php',
            'plugin_slug' => 'elementor',
            'plugin_version' => '3.32.5',
            'relative_path' => 'vendor/file.php',
            'sha256' => str_repeat('c', 64),
            'status_label' => 'Needs Verification',
            'classification' => 'suspicious',
            'score' => 45,
        ])->assertStatus(422);
    }

    public function test_enable_disable_and_delete_actions_are_audited(): void
    {
        $record = VerifiedSafeFile::create([
            'plugin_slug' => 'custom-plugin',
            'plugin_version' => '2.0.0',
            'relative_path' => 'includes/helper.php',
            'sha256' => str_repeat('d', 64),
            'verified_by' => $this->admin->id,
            'enabled' => true,
        ]);

        $this->actingAs($this->admin);

        $this->postJson("/api/v1/verified-safe-files/{$record->id}/disable")
            ->assertOk()
            ->assertJsonPath('record.enabled', false);

        $this->postJson("/api/v1/verified-safe-files/{$record->id}/enable")
            ->assertOk()
            ->assertJsonPath('record.enabled', true);

        $this->deleteJson("/api/v1/verified-safe-files/{$record->id}")
            ->assertOk();

        $this->assertDatabaseMissing('verified_safe_files', ['id' => $record->id]);
        $this->assertTrue(
            AdminSecurityLog::query()->where('event', 'verified_safe.removed')->exists()
        );
    }

    public function test_sync_payload_includes_enabled_fingerprints(): void
    {
        VerifiedSafeFile::create([
            'plugin_slug' => 'premium-plugin',
            'plugin_version' => '4.1.0',
            'relative_path' => 'lib/loader.php',
            'sha256' => str_repeat('e', 64),
            'enabled' => true,
        ]);

        VerifiedSafeFile::create([
            'plugin_slug' => 'premium-plugin',
            'plugin_version' => '4.0.0',
            'relative_path' => 'lib/loader.php',
            'sha256' => str_repeat('f', 64),
            'enabled' => false,
        ]);

        app(VerifiedSafeFileSyncService::class)->invalidateCache();

        $this->actingAs($this->admin);

        $response = $this->getJson('/api/v1/verified-safe-files/sync');

        $response->assertOk()
            ->assertJsonCount(2, 'verified_safe_files')
            ->assertJsonStructure(['verified_safe_files_version']);
    }

    public function test_history_endpoint_returns_version_records(): void
    {
        VerifiedSafeFile::create([
            'plugin_slug' => 'elementor',
            'plugin_version' => '3.30.1',
            'relative_path' => 'vendor/env.php',
            'sha256' => str_repeat('1', 64),
            'enabled' => true,
        ]);

        VerifiedSafeFile::create([
            'plugin_slug' => 'elementor',
            'plugin_version' => '3.33.0',
            'relative_path' => 'vendor/env.php',
            'sha256' => str_repeat('2', 64),
            'enabled' => true,
        ]);

        $this->actingAs($this->admin);

        $this->getJson('/api/v1/verified-safe-files/history?plugin_slug=elementor&relative_path=vendor/env.php')
            ->assertOk()
            ->assertJsonCount(2, 'history');
    }

    public function test_malware_reports_hide_verified_safe_findings_on_read(): void
    {
        $sha256 = str_repeat('a', 64);

        VerifiedSafeFile::create([
            'plugin_slug' => 'elementor',
            'plugin_version' => '3.32.5',
            'relative_path' => 'vendor/env.php',
            'sha256' => $sha256,
            'enabled' => true,
        ]);

        app(VerifiedSafeFileSyncService::class)->invalidateCache();

        $agent = \App\Features\Agent\Models\Agent::create([
            'domain' => 'suppress-read.test',
            'site_name' => 'Suppress Read Site',
            'status' => 'active',
            'hmac_secret' => str_repeat('a', 32),
        ]);

        \App\Features\Monitoring\Models\MalwareReport::create([
            'agent_id' => $agent->id,
            'files_scanned' => 10,
            'malicious_files_found' => 0,
            'threat_details' => [
                'engine_version' => '2.2',
                'files' => [[
                    'path' => 'wp-content/plugins/elementor/vendor/env.php',
                    'type' => 'PHP.Info.Eval',
                    'score' => 45,
                    'classification' => 'suspicious',
                    'status_label' => 'Needs Verification',
                    'plugin_slug' => 'elementor',
                    'plugin_version' => '3.32.5',
                    'relative_path' => 'vendor/env.php',
                    'sha256' => $sha256,
                ]],
            ],
            'scanned_at' => now(),
        ]);

        $this->actingAs($this->admin);

        $this->getJson('/api/v1/malware-reports')
            ->assertOk()
            ->assertJsonCount(0, 'reports.0.threat_files')
            ->assertJsonPath('reports.0.threat_summary.total_findings', 0);
    }

    public function test_verify_safe_endpoint_is_rate_limited(): void
    {
        $this->actingAs($this->admin);

        $report = $this->createReportWithFinding([
            'sha256' => str_repeat('e', 64),
            'path' => 'wp-content/plugins/elementor/vendor/rate.php',
            'relative_path' => 'vendor/rate.php',
        ]);

        $payload = [
            'malware_report_id' => $report->id,
            'finding_path' => 'wp-content/plugins/elementor/vendor/rate.php',
            'plugin_slug' => 'elementor',
            'plugin_version' => '3.32.5',
            'relative_path' => 'vendor/rate.php',
            'sha256' => str_repeat('e', 64),
            'status_label' => 'Needs Verification',
            'classification' => 'suspicious',
            'score' => 45,
        ];

        for ($i = 0; $i < 20; $i++) {
            $this->postJson('/api/v1/verified-safe-files', $payload);
        }

        $this->postJson('/api/v1/verified-safe-files', $payload)
            ->assertStatus(429);
    }

    public function test_heartbeat_omits_fingerprints_when_agent_version_matches(): void
    {
        VerifiedSafeFile::create([
            'plugin_slug' => 'elementor',
            'plugin_version' => '3.32.5',
            'relative_path' => 'vendor/env.php',
            'sha256' => str_repeat('f', 64),
            'enabled' => true,
        ]);

        $sync = app(VerifiedSafeFileSyncService::class);
        $sync->invalidateCache();
        $version = $sync->getVersionHash();

        $agent = \App\Features\Agent\Models\Agent::create([
            'domain' => 'heartbeat-sync.test',
            'site_name' => 'Heartbeat Sync Site',
            'status' => 'active',
            'hmac_secret' => 'heartbeat-sync-secret-key-12345',
        ]);

        $body = [
            'status' => 'ok',
            'verified_safe_files_version' => $version,
        ];

        $uri = '/api/v1/agent/telemetry';
        $timestamp = time();
        $nonce = uniqid('', true);
        $rawBody = json_encode($body);
        $payload = implode('|', ['POST', $uri, $timestamp, $nonce, $rawBody]);
        $signature = hash_hmac('sha256', $payload, $agent->hmac_secret);

        $response = $this->postJson($uri, $body, [
            'X-AMG-Agent-ID' => $agent->id,
            'X-AMG-Timestamp' => (string) $timestamp,
            'X-AMG-Nonce' => $nonce,
            'X-AMG-Signature' => $signature,
        ]);

        $response->assertOk()
            ->assertJsonPath('policy.verified_safe_files_version', $version)
            ->assertJsonMissing(['policy' => ['verified_safe_files' => []]]);

        $policy = $response->json('policy');
        $this->assertArrayNotHasKey('verified_safe_files', $policy);
    }

    /**
     * @param array<string, mixed> $overrides
     */
    private function createReportWithFinding(array $overrides = []): \App\Features\Monitoring\Models\MalwareReport
    {
        $agent = \App\Features\Agent\Models\Agent::create([
            'domain' => 'verify-safe-' . uniqid('', true) . '.test',
            'site_name' => 'Verify Safe Site',
            'status' => 'active',
            'hmac_secret' => str_repeat('a', 32),
        ]);

        $finding = array_merge([
            'path' => 'wp-content/plugins/elementor/vendor/env.php',
            'type' => 'PHP.Info.Eval',
            'score' => 45,
            'classification' => 'suspicious',
            'status_label' => 'Needs Verification',
            'plugin_slug' => 'elementor',
            'plugin_name' => 'Elementor',
            'plugin_version' => '3.32.5',
            'relative_path' => 'vendor/env.php',
            'sha256' => str_repeat('a', 64),
        ], $overrides);

        return \App\Features\Monitoring\Models\MalwareReport::create([
            'agent_id' => $agent->id,
            'files_scanned' => 10,
            'malicious_files_found' => 0,
            'threat_details' => [
                'engine_version' => '2.2',
                'files' => [$finding],
            ],
            'scanned_at' => now(),
        ]);
    }
}
