# -*- coding: utf-8 -*-
"""语音识别 —— 阿里云 DashScope paraformer-realtime-v2（流式）
   前端录音上传（m4a/wav/ogg/opus/pcm）→ 这里转写为文本
"""

import logging
import os
import time

import certifi

# macOS 系统 Python 无系统 CA：必须在导入 dashscope 之前设置，
# aiohttp 才会使用 certifi 根证书（否则 WS 连接报 SSL 证书错误）
os.environ.setdefault("SSL_CERT_FILE", certifi.where())

import dashscope  # noqa: E402
from dashscope.audio.asr import Recognition, RecognitionCallback  # noqa: E402

from .config import settings  # noqa: E402

log = logging.getLogger("dpm.asr")


def _err_text(result):
    """安全提取 RecognitionResult 的错误描述（其 __str__ 有缺陷）"""
    for attr in ("message", "code"):
        v = getattr(result, attr, None)
        if v:
            return f"{attr}={v}"
    return repr(result)

# 前端 MediaRecorder 可能产生的容器/编码 → paraformer 格式名
FORMAT_ALIASES = {
    "mp4": "m4a", "m4a": "m4a", "aac": "m4a",
    "webm": "ogg", "opus": "opus", "ogg": "ogg",
    "wav": "wav", "pcm": "pcm", "mp3": "mp3",
}

# m4a/mp3 等压缩格式采样率由服务端自动识别
_AUTO_SAMPLE_FORMATS = {"m4a", "mp3", "ogg", "opus", "wav"}


class _Callback(RecognitionCallback):
    def __init__(self):
        self.sentences = []
        self.error = None

    def on_message(self, message):
        try:
            header = message.get("header", {})
            if header.get("action") != "result":
                return
            payload = message.get("payload", {})
            sentences = payload.get("sentence", {}).get("sentences") or []
            for s in sentences:
                if s.get("sentence_end"):
                    self.sentences.append(s.get("text", ""))
        except Exception as e:  # noqa: BLE001
            log.warning("ASR 消息解析异常: %s", e)

    def on_error(self, result):
        self.error = result
        log.warning("ASR 错误: %s", _err_text(result))


def transcribe(audio_bytes: bytes, fmt: str = "m4a") -> str:
    """上传音频字节 → 返回转写文本（空串表示未识别到内容）"""
    if not settings.DASHSCOPE_API_KEY:
        raise RuntimeError("未配置 DASHSCOPE_API_KEY，无法使用阿里云语音识别")

    dashscope.api_key = settings.DASHSCOPE_API_KEY
    fmt = FORMAT_ALIASES.get((fmt or "m4a").lower().lstrip("."), "m4a")

    cb = _Callback()
    rec = Recognition(
        model=settings.ASR_MODEL,
        format=fmt,
        sample_rate=16000 if fmt in ("pcm", "wav") else 0,  # 压缩格式自动识别
        callback=cb,
    )

    # 分块发送，模拟流式（适当间隔，避免触发服务端 batching 报错）
    rec.start()
    chunk = 16 * 1024
    for i in range(0, len(audio_bytes), chunk):
        rec.send_audio_frame(audio_bytes[i:i + chunk])
        time.sleep(0.08)
    time.sleep(0.5)  # 等待尾部识别
    rec.stop()

    if cb.error:
        raise RuntimeError(f"阿里云语音识别失败: {_err_text(cb.error)}")
    return "".join(cb.sentences).strip()
