"""引擎接口与单次识别结果。

两类引擎统一到 transcribe()，但计时口径不同：
  - streaming（gummy）：有首包延迟 first_partial_sec、定稿延迟 finalize_sec。
  - offline（本地）：只有总处理时长与 RTF；资源探针在 runner 层包裹（仅本地）。
"""

from __future__ import annotations

from dataclasses import dataclass


@dataclass
class Transcript:
    text: str
    audio_sec: float
    proc_sec: float                      # transcribe 墙钟耗时
    first_partial_sec: float | None = None
    finalize_sec: float | None = None
    peak_rss_mb: float | None = None     # 由 runner 的 ResourceProbe 回填（本地引擎）
    avg_cpu: float | None = None
    error: str | None = None

    @property
    def rtf(self) -> float | None:
        if not self.audio_sec:
            return None
        return self.proc_sec / self.audio_sec


class Engine:
    """引擎基类。子类至少实现 transcribe()；load()/unload() 处理重模型生命周期。"""

    name: str = "base"
    kind: str = "offline"   # "offline" | "streaming"
    is_local: bool = True

    def load(self) -> None:
        """加载模型（本地引擎重操作）。云端引擎可空实现。"""

    def transcribe(self, audio_path: str) -> Transcript:
        raise NotImplementedError

    def unload(self) -> None:
        """释放模型，便于多引擎串行评估时回收内存。"""

    def model_size_mb(self) -> float | None:
        """磁盘上模型权重大小（MB）；云端返回 None。"""
        return None

    def cost_per_min(self) -> float | None:
        """每分钟成本（云端）；本地返回 None。"""
        return None
