<?php

namespace App\Jobs;

use App\Models\Document;
use App\Services\DocumentConversionService;
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;

/**
 * 文档转换为 Markdown 的队列任务
 */
class ConvertDocumentToMarkdown implements ShouldQueue
{
    use Dispatchable, InteractsWithQueue, Queueable, SerializesModels;

    public $tries;
    public $timeout;
    public $backoff;

    protected Document $document;

    public function __construct(Document $document)
    {
        $this->document = $document;
        $this->tries = config('documents.conversion.retry_times', 3);
        $this->timeout = config('documents.conversion.timeout', 300);
        $this->backoff = config('documents.conversion.retry_delay', 60);
    }

    public function handle(DocumentConversionService $conversionService): void
    {
        try {
            Log::info('开始转换文档', [
                'document_id' => $this->document->id,
                'document_title' => $this->document->title,
                'file_name' => $this->document->file_name,
                'attempt' => $this->attempts(),
            ]);

            $result = $conversionService->convertToMarkdown($this->document);

            $markdownPath = $conversionService->saveMarkdownToFile(
                $this->document,
                $result['markdown'],
                $result['media_files'] ?? []
            );

            $conversionService->updateDocumentMarkdown($this->document, $markdownPath);

            Log::info('文档转换成功', [
                'document_id' => $this->document->id,
                'document_title' => $this->document->title,
                'markdown_path' => $markdownPath,
            ]);
        } catch (\Throwable $e) {
            $exception = $this->normalizeException($e);

            Log::error('文档转换失败', [
                'document_id' => $this->document->id,
                'document_title' => $this->document->title,
                'file_name' => $this->document->file_name,
                'attempt' => $this->attempts(),
                'error' => $exception->getMessage(),
            ]);

            if ($this->attempts() >= $this->tries) {
                $conversionService->handleConversionFailure($this->document, $exception);
            }

            throw $exception;
        }
    }

    public function failed(\Throwable $exception): void
    {
        $normalized = $this->normalizeException($exception);

        Log::error('文档转换任务最终失败', [
            'document_id' => $this->document->id,
            'document_title' => $this->document->title,
            'file_name' => $this->document->file_name,
            'error' => $normalized->getMessage(),
        ]);

        $conversionService = app(DocumentConversionService::class);
        $conversionService->handleConversionFailure($this->document, $normalized);
    }

    protected function normalizeException(\Throwable $throwable): \Exception
    {
        if ($throwable instanceof \Exception) {
            return $throwable;
        }

        return new \RuntimeException($throwable->getMessage(), 0, $throwable);
    }
}
