from __future__ import annotations

import shutil
from dataclasses import dataclass
from typing import Optional

from PyQt6.QtCore import QObject, QThread, pyqtSignal

from ..core.media import extract_audio_to_wav, is_video
from ..core.whisper_engine import TranscribeOptions, ensure_model_available, transcribe_file


class ModelInitWorker(QObject):
    finished = pyqtSignal()
    error = pyqtSignal(str)

    def __init__(self, opts: TranscribeOptions):
        super().__init__()
        self.opts = opts

    def run(self) -> None:
        try:
            ensure_model_available(self.opts)
            self.finished.emit()
        except Exception as e:
            self.error.emit(str(e))


@dataclass
class TranscriptionJob:
    input_path: str
    opts: TranscribeOptions


class TranscribeWorker(QObject):
    finished = pyqtSignal(str)
    error = pyqtSignal(str)

    def __init__(self, job: TranscriptionJob):
        super().__init__()
        self.job = job

    def run(self) -> None:
        temp_dir: Optional[str] = None
        audio_path = self.job.input_path
        try:
            if is_video(audio_path):
                wav_path, temp_dir = extract_audio_to_wav(audio_path)
                audio_path = wav_path

            text = transcribe_file(audio_path, self.job.opts)
            self.finished.emit(text)
        except Exception as e:
            self.error.emit(str(e))
        finally:
            if temp_dir:
                shutil.rmtree(temp_dir, ignore_errors=True)


def start_in_thread(worker: QObject, fn_name: str = "run") -> QThread:
    thread = QThread()
    thread._worker = worker  # type: ignore[attr-defined]
    worker.moveToThread(thread)
    thread.started.connect(getattr(worker, fn_name))
    if hasattr(worker, "finished"):
        getattr(worker, "finished").connect(thread.quit)  # type: ignore[attr-defined]
    if hasattr(worker, "error"):
        getattr(worker, "error").connect(thread.quit)     # type: ignore[attr-defined]
    thread.start()
    return thread
