"""
TTS 語音生成器 - 使用 Edge TTS 將文字轉換為語音

功能：
1. 將文字轉換為 MP3 語音檔
2. 支援多種語音和風格選項
3. 自動管理輸出檔案和版本
"""

import asyncio
import re
from pathlib import Path
from dataclasses import dataclass
from datetime import date
from typing import Optional

import edge_tts

from .config import (
    get_voice, get_style, ensure_directories,
    AUDIO_DIR, OUTPUT_DIR, VoiceConfig, StyleConfig
)
from .extractor import ResearchNote


@dataclass
class GenerationResult:
    """語音生成結果"""
    success: bool
    output_path: Optional[Path]
    duration_estimate: Optional[str]  # 預估時長
    file_size: Optional[int]  # 檔案大小 (bytes)
    error_message: Optional[str] = None


class TTSGenerator:
    """Edge TTS 語音生成器"""

    def __init__(
        self,
        voice: Optional[str] = None,
        style: Optional[str] = None
    ):
        """
        初始化生成器

        Args:
            voice: 語音選項 (female_1, female_2, male)
            style: 風格選項 (formal, professional, secretary, fast)
        """
        self.voice_config = get_voice(voice)
        self.style_config = get_style(style)
        ensure_directories()

    async def generate(
        self,
        text: str,
        output_path: Path,
        voice_config: Optional[VoiceConfig] = None,
        style_config: Optional[StyleConfig] = None
    ) -> GenerationResult:
        """
        生成語音檔案

        Args:
            text: 要轉換的文字
            output_path: 輸出檔案路徑
            voice_config: 覆寫預設語音設定
            style_config: 覆寫預設風格設定

        Returns:
            GenerationResult 物件
        """
        voice = voice_config or self.voice_config
        style = style_config or self.style_config

        try:
            # 建立 Edge TTS Communicate 物件
            communicate = edge_tts.Communicate(
                text,
                voice=voice.voice_id,
                rate=style.rate,
                pitch=style.pitch
            )

            # 確保輸出目錄存在
            output_path.parent.mkdir(parents=True, exist_ok=True)

            # 生成並儲存
            await communicate.save(str(output_path))

            # 取得檔案資訊
            file_size = output_path.stat().st_size if output_path.exists() else 0

            # 預估時長（根據檔案大小，128kbps ≈ 16KB/秒）
            duration_seconds = file_size / (16 * 1024) if file_size > 0 else 0
            minutes = int(duration_seconds // 60)
            seconds = int(duration_seconds % 60)
            duration_str = f"{minutes}:{seconds:02d}"

            return GenerationResult(
                success=True,
                output_path=output_path,
                duration_estimate=duration_str,
                file_size=file_size
            )

        except Exception as e:
            return GenerationResult(
                success=False,
                output_path=None,
                duration_estimate=None,
                file_size=None,
                error_message=str(e)
            )

    async def generate_from_note(
        self,
        note: ResearchNote,
        output_dir: Optional[Path] = None,
        version: int = 1
    ) -> GenerationResult:
        """
        從研究筆記生成語音

        Args:
            note: ResearchNote 物件
            output_dir: 輸出目錄（預設為 audio/YYYY/MM/）
            version: 版本號

        Returns:
            GenerationResult 物件
        """
        # 決定輸出路徑
        if output_dir is None:
            # 使用 audio/YYYY/MM/ 結構
            year = note.created_at.year
            month = note.created_at.month
            output_dir = AUDIO_DIR / str(year) / f"{month:02d}"

        # 生成檔名：{date}-{slug}-summary-v{version}.mp3
        slug = self._generate_slug(note.note_id)
        filename = f"{slug}-summary-v{version}.mp3"
        output_path = output_dir / filename

        # 生成語音
        result = await self.generate(note.summary_text, output_path)

        return result

    def _generate_slug(self, note_id: str) -> str:
        """從筆記 ID 生成檔名 slug"""
        # 移除特殊字元，保留字母數字和連字號
        slug = re.sub(r'[^\w\-]', '-', note_id)
        # 移除連續的連字號
        slug = re.sub(r'-+', '-', slug)
        # 移除開頭結尾的連字號
        slug = slug.strip('-')
        return slug


def generate_speech(
    text: str,
    output_path: str | Path,
    voice: Optional[str] = None,
    style: Optional[str] = None
) -> GenerationResult:
    """
    便捷函數：生成語音檔案

    Args:
        text: 要轉換的文字
        output_path: 輸出檔案路徑
        voice: 語音選項
        style: 風格選項

    Returns:
        GenerationResult 物件
    """
    generator = TTSGenerator(voice=voice, style=style)
    return asyncio.run(generator.generate(text, Path(output_path)))


def generate_from_note(
    note: ResearchNote,
    output_dir: Optional[str | Path] = None,
    version: int = 1,
    voice: Optional[str] = None,
    style: Optional[str] = None
) -> GenerationResult:
    """
    便捷函數：從研究筆記生成語音

    Args:
        note: ResearchNote 物件
        output_dir: 輸出目錄
        version: 版本號
        voice: 語音選項
        style: 風格選項

    Returns:
        GenerationResult 物件
    """
    generator = TTSGenerator(voice=voice, style=style)
    output_path = Path(output_dir) if output_dir else None
    return asyncio.run(generator.generate_from_note(note, output_path, version))


async def list_available_voices() -> list[dict]:
    """列出所有可用的語音"""
    voices = await edge_tts.list_voices()
    # 過濾台灣中文語音
    zh_tw_voices = [v for v in voices if "zh-TW" in v.get("ShortName", "")]
    return zh_tw_voices
