<?php

namespace App\Jobs;

use App\Models\EventMediaAsset;
use App\Models\Photo;
use App\Services\Security\PhotoSecurityScanner;
use Illuminate\Bus\Queueable;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Bus\Dispatchable;
use Illuminate\Queue\InteractsWithQueue;
use Illuminate\Queue\SerializesModels;
use Illuminate\Support\Facades\Log;

class ProcessPhotoSecurityScan implements ShouldQueue
{
    use Dispatchable;
    use InteractsWithQueue;
    use Queueable;
    use SerializesModels;

    public function __construct(public int $photoId)
    {
        $this->queue = config('security.queue.name', 'default');
    }

    public function handle(PhotoSecurityScanner $scanner): void
    {
        $photo = Photo::with('mediaAsset')->find($this->photoId);

        if (! $photo) {
            Log::warning('[PhotoSecurity] Skipping missing photo', ['photo_id' => $this->photoId]);
            return;
        }

        $asset = $photo->mediaAsset ?? EventMediaAsset::where('photo_id', $photo->id)->where('variant', 'original')->first();

        if (! $asset) {
            Log::warning('[PhotoSecurity] No media asset available for scan', [
                'photo_id' => $photo->id,
            ]);

            $photo->forceFill([
                'security_scan_status' => 'error',
                'security_scan_message' => 'Media asset not available for scanning.',
                'security_scanned_at' => now(),
            ])->save();

            return;
        }

        $disk = $asset->disk ?? config('filesystems.default', 'public');
        $path = $asset->path ?? $photo->file_path;

        $scanResult = $scanner->scan($disk, $path);
        $status = $scanResult['status'] ?? 'error';
        $message = $scanResult['message'] ?? null;

        $metadata = [
            'scan' => $scanResult,
        ];

        if ($status === 'clean' && config('security.exif.strip', true)) {
            $stripResult = $scanner->stripExif($disk, $path);
            $metadata['exif'] = $stripResult;
        }

        $existingMeta = $photo->security_meta ?? [];

        $update = [
            'security_scan_status' => $status,
            'security_scan_message' => $message,
            'security_scanned_at' => now(),
            'security_meta' => array_merge(is_array($existingMeta) ? $existingMeta : [], $metadata),
        ];

        if (in_array($status, ['clean', 'skipped'], true) && $photo->status === 'pending') {
            $update['status'] = 'approved';
        }

        if ($status === 'infected') {
            $update['status'] = 'rejected';
        }

        $photo->forceFill($update)->save();

        if ($status === 'infected') {
            Log::alert('[PhotoSecurity] Infected photo detected', [
                'photo_id' => $photo->id,
                'event_id' => $photo->event_id,
                'message' => $message,
            ]);
        }
    }
}
