<?php

namespace App\Jobs;

use App\Contracts\ResumeAnalyzer;
use App\Contracts\ResumeTextExtractor;
use App\Models\ResumeReport;
use Illuminate\Contracts\Queue\ShouldQueue;
use Illuminate\Foundation\Queue\Queueable;
use Throwable;

class AnalyzeResume implements ShouldQueue
{
    use Queueable;

    public int $tries = 3;

    public int $timeout = 120;

    /**
     * Create a new job instance.
     */
    public function __construct(public ResumeReport $resumeReport) {}

    /**
     * Execute the job.
     */
    public function handle(ResumeTextExtractor $resumeTextExtractor, ResumeAnalyzer $resumeAnalyzer): void
    {
        $this->resumeReport->refresh();

        $this->resumeReport->forceFill([
            'status' => ResumeReport::STATUS_PROCESSING,
            'failure_reason' => null,
        ])->save();

        try {
            $resumeText = $resumeTextExtractor->extract($this->resumeReport);

            if (mb_strlen($resumeText) < 100) {
                $this->markFailed('Resume text could not be extracted clearly enough for analysis.');

                return;
            }

            $analysis = $resumeAnalyzer->analyze($resumeText);

            $this->resumeReport->forceFill([
                'status' => ResumeReport::STATUS_COMPLETED,
                'ats_score' => $this->score($analysis['ats_score'] ?? null),
                'remote_readiness_score' => $this->score($analysis['remote_readiness_score'] ?? null),
                'extracted_skills' => $analysis['extracted_skills'] ?? [],
                'role_suggestions' => $analysis['role_suggestions'] ?? [],
                'missing_keywords' => $analysis['missing_keywords'] ?? [],
                'resume_improvements' => $analysis['resume_improvements'] ?? [],
                'analysis' => $analysis,
                'failure_reason' => null,
                'analyzed_at' => now(),
            ])->save();

            $this->resumeReport->user()->update([
                'resume_analyzed_at' => now(),
            ]);
        } catch (Throwable $exception) {
            report($exception);

            $this->markFailed('Resume analysis failed. Please try uploading again.');
        }
    }

    private function score(mixed $score): int
    {
        return min(100, max(0, (int) $score));
    }

    private function markFailed(string $reason): void
    {
        $this->resumeReport->forceFill([
            'status' => ResumeReport::STATUS_FAILED,
            'failure_reason' => $reason,
            'analyzed_at' => null,
        ])->save();
    }
}
