<?php

namespace App\Jobs;

use App\Models\JobApplication;
use App\Models\User;
use App\Notifications\CvInfectedNotification;
use App\Notifications\CvScanFailedNotification;
use App\Services\VirusTotalService;
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\Storage;
use Illuminate\Support\Facades\Log;
use Spatie\Permission\Models\Role;

class ScanCvWithVirusTotal implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    public int $tries = 1;
    public int $timeout = 120;

    public function __construct(
        protected JobApplication $application
    ) {}

    public function handle(VirusTotalService $virusTotal): void
    {
        // VirusTotal devre dışıysa atla
        if (!$virusTotal->isEnabled()) {
            $this->application->update(['cv_scan_status' => 'skipped']);
            return;
        }

        // Dosya mevcut mu?
        if (!Storage::disk('local')->exists($this->application->cv_path)) {
            $this->application->update(['cv_scan_status' => 'failed']);
            $this->notifyAdmins('failed', 'CV dosyası bulunamadı.');
            return;
        }

        $filePath = Storage::disk('local')->path($this->application->cv_path);

        // Dosyayı VirusTotal'e gönder
        $scanResult = $virusTotal->scan($filePath);

        // API key yok — sessizce atla, bildirim gönderme
        if (isset($scanResult['error']) && $scanResult['error'] === 'no_api_key') {
            $this->application->update([
                'cv_scan_status' => 'skipped',
                'cv_scanned_at'  => now(),
            ]);
            return;
        }

        // Rate limit kontrolü
        if ($virusTotal->isLimitExceeded($scanResult)) {
            $this->application->update([
                'cv_scan_status' => 'skipped',
                'cv_scanned_at'  => now(),
            ]);
            $this->notifyAdmins('limit', 'Günlük VirusTotal API limiti doldu. CV taraması yapılamadı.');
            return;
        }

        // API hatası
        if (isset($scanResult['error'])) {
            $this->application->update([
                'cv_scan_status' => 'failed',
                'cv_scanned_at'  => now(),
            ]);
            $this->notifyAdmins('failed', $scanResult['message'] ?? 'Bilinmeyen hata.');
            return;
        }

        $analysisId = $scanResult['analysis_id'] ?? null;

        if (!$analysisId) {
            $this->application->update(['cv_scan_status' => 'failed', 'cv_scanned_at' => now()]);
            return;
        }

        // Sonucu bekle
        $result = $virusTotal->waitForResult($analysisId);

        if (isset($result['error'])) {
            if ($virusTotal->isLimitExceeded($result)) {
                $this->application->update(['cv_scan_status' => 'skipped', 'cv_scanned_at' => now()]);
                $this->notifyAdmins('limit', 'Günlük VirusTotal API limiti doldu.');
            } else {
                $this->application->update(['cv_scan_status' => 'failed', 'cv_scanned_at' => now()]);
                $this->notifyAdmins('failed', $result['message'] ?? 'Analiz sonucu alınamadı.');
            }
            return;
        }

        $isClean = $virusTotal->isClean($result['data'] ?? []);

        $this->application->update([
            'cv_scan_status' => $isClean ? 'clean' : 'infected',
            'cv_scan_result' => $result['data'] ?? [],
            'cv_scanned_at'  => now(),
        ]);

        if (!$isClean) {
            $this->notifyAdmins('infected', 'CV dosyasında virüs/zararlı yazılım tespit edildi!');
        }
    }

    protected function notifyAdmins(string $type, string $message): void
    {
        try {
            $admins = User::role(['super-admin', 'hr-manager'])->get();

            foreach ($admins as $admin) {
                if ($type === 'infected') {
                    $admin->notify(new CvInfectedNotification($this->application, $message));
                } else {
                    $admin->notify(new CvScanFailedNotification($this->application, $message, $type));
                }
            }
        } catch (\Exception $e) {
            Log::error('CV scan notification error: ' . $e->getMessage());
        }
    }

    public function failed(\Throwable $exception): void
    {
        Log::error('ScanCvWithVirusTotal job failed for application #' . $this->application->id . ': ' . $exception->getMessage());

        $this->application->update([
            'cv_scan_status' => 'failed',
            'cv_scanned_at'  => now(),
        ]);
    }
}