"""Konvertierungs-Job-Modell mit Status-Management"""
import time
import asyncio
from dataclasses import dataclass, field
from enum import IntEnum
from typing import Optional
from app.models.media import MediaFile

# Globaler Zaehler fuer eindeutige IDs
_id_counter = 0


class JobStatus(IntEnum):
    QUEUED = 0
    ACTIVE = 1
    FINISHED = 2
    FAILED = 3
    CANCELLED = 4


@dataclass
class ConversionJob:
    """Einzelner Konvertierungs-Auftrag"""
    media: MediaFile
    preset_name: str = ""

    # Wird in __post_init__ gesetzt
    id: int = field(init=False)
    status: JobStatus = field(default=JobStatus.QUEUED)

    # Ziel-Informationen
    target_path: str = ""
    target_filename: str = ""
    target_container: str = "webm"

    # Optionen
    delete_source: bool = False  # Quelldatei nach Konvertierung loeschen

    # ffmpeg Prozess
    ffmpeg_cmd: list[str] = field(default_factory=list)
    process: Optional[asyncio.subprocess.Process] = field(default=None, repr=False)
    task: Optional[asyncio.Task] = field(default=None, repr=False)

    # Fortschritt
    progress_percent: float = 0.0
    progress_fps: float = 0.0
    progress_speed: float = 0.0
    progress_bitrate: int = 0
    progress_size_bytes: int = 0
    progress_time_sec: float = 0.0
    progress_frames: int = 0
    progress_eta_sec: float = 0.0

    # Zeitstempel
    created_at: float = field(default_factory=time.time)
    started_at: Optional[float] = None
    finished_at: Optional[float] = None

    # Statistik-Akkumulation (Summe, Anzahl)
    _stat_fps: list = field(default_factory=lambda: [0.0, 0])
    _stat_speed: list = field(default_factory=lambda: [0.0, 0])
    _stat_bitrate: list = field(default_factory=lambda: [0, 0])

    def __post_init__(self) -> None:
        global _id_counter
        self.id = int(time.time() * 1000) * 1000 + _id_counter
        _id_counter += 1

    def build_target_path(self, config) -> None:
        """Baut Ziel-Pfad basierend auf Config"""
        files_cfg = config.files_config
        container = files_cfg.get("target_container", "webm")
        self.target_container = container

        # Dateiname ohne Extension + neue Extension
        base_name = self.media.source_filename.rsplit(".", 1)[0]
        self.target_filename = f"{base_name}.{container}"

        # Ziel-Ordner
        target_folder = files_cfg.get("target_folder", "same")
        if target_folder == "same":
            target_dir = self.media.source_dir
        else:
            target_dir = target_folder

        self.target_path = f"{target_dir}/{self.target_filename}"

        # Konfliktvermeidung: Wenn Ziel = Quelle (gleiche Extension)
        if self.target_path == self.media.source_path:
            base = self.target_path.rsplit(".", 1)[0]
            self.target_path = f"{base}_converted.{container}"
            self.target_filename = f"{base_name}_converted.{container}"

    def update_stats(self, fps: float, speed: float, bitrate: int) -> None:
        """Akkumuliert Statistik-Werte fuer Durchschnittsberechnung"""
        if fps > 0:
            self._stat_fps[0] += fps
            self._stat_fps[1] += 1
        if speed > 0:
            self._stat_speed[0] += speed
            self._stat_speed[1] += 1
        if bitrate > 0:
            self._stat_bitrate[0] += bitrate
            self._stat_bitrate[1] += 1

    @property
    def avg_fps(self) -> float:
        if self._stat_fps[1] > 0:
            return self._stat_fps[0] / self._stat_fps[1]
        return 0.0

    @property
    def avg_speed(self) -> float:
        if self._stat_speed[1] > 0:
            return self._stat_speed[0] / self._stat_speed[1]
        return 0.0

    @property
    def avg_bitrate(self) -> int:
        if self._stat_bitrate[1] > 0:
            return int(self._stat_bitrate[0] / self._stat_bitrate[1])
        return 0

    @property
    def duration_sec(self) -> float:
        """Konvertierungsdauer in Sekunden"""
        if self.started_at and self.finished_at:
            return self.finished_at - self.started_at
        return 0.0

    def to_dict_active(self) -> dict:
        """Fuer WebSocket data_convert Nachricht"""
        size = MediaFile.format_size(self.media.source_size_bytes)
        return {
            "source_file_name": self.media.source_filename,
            "source_file": self.media.source_path,
            "source_path": self.media.source_dir,
            "source_duration": self.media.source_duration_sec,
            "source_size": [size[0], size[1]],
            "source_frame_rate": self.media.frame_rate,
            "source_frames_total": self.media.total_frames,
            "target_file_name": self.target_filename,
            "target_file": self.target_path,
            "status": self.status.value,
            "preset": self.preset_name,
        }

    def to_dict_queue(self) -> dict:
        """Fuer WebSocket data_queue Nachricht"""
        return {
            "source_file_name": self.media.source_filename,
            "source_file": self.media.source_path,
            "source_path": self.media.source_dir,
            "status": self.status.value,
            "preset": self.preset_name,
        }

    def to_dict_progress(self) -> dict:
        """Fuer WebSocket data_flow Nachricht"""
        target_size = MediaFile.format_size(self.progress_size_bytes)
        return {
            "id": self.id,
            "frames": self.progress_frames,
            "fps": self.progress_fps,
            "speed": self.progress_speed,
            "quantizer": 0,
            "size": [target_size[0], target_size[1]],
            "time": MediaFile.format_time(self.progress_time_sec),
            "time_remaining": MediaFile.format_time(self.progress_eta_sec),
            "loading": round(self.progress_percent, 1),
            "bitrate": [self.progress_bitrate, "kbits/s"],
        }

    def to_dict_stats(self) -> dict:
        """Fuer Statistik-Datenbank"""
        return {
            "source_path": self.media.source_path,
            "source_filename": self.media.source_filename,
            "source_size_bytes": self.media.source_size_bytes,
            "source_duration_sec": self.media.source_duration_sec,
            "source_frame_rate": self.media.frame_rate,
            "source_frames_total": self.media.total_frames,
            "target_path": self.target_path,
            "target_filename": self.target_filename,
            "target_size_bytes": self.progress_size_bytes,
            "target_container": self.target_container,
            "preset_name": self.preset_name,
            "status": self.status.value,
            "started_at": self.started_at,
            "finished_at": self.finished_at,
            "duration_sec": self.duration_sec,
            "avg_fps": self.avg_fps,
            "avg_speed": self.avg_speed,
            "avg_bitrate": self.avg_bitrate,
        }

    def to_json(self) -> dict:
        """Fuer Queue-Persistierung"""
        return {
            "source_path": self.media.source_path,
            "preset_name": self.preset_name,
            "status": self.status.value,
            "created_at": self.created_at,
            "delete_source": self.delete_source,
        }
