#!/usr/bin/env python3
"""
Convierte los ficheros *_audio.md de todos los bloques a MP3.

Uso:
  python3 scripts/temas_a_audio.py                     # procesa todos los bloques
  python3 scripts/temas_a_audio.py 2                   # solo bloque2
  python3 scripts/temas_a_audio.py 2 3                 # bloque2 y bloque3
  python3 scripts/temas_a_audio.py src/.../tema2_audio.md  # fichero concreto

Dependencias:  pip install edge-tts
Requisitos:    ffmpeg instalado en el sistema

Fuente:  src/main/resources/temas/bloqueX/*_audio.md
Destino: src/main/resources/static/audios/bloqueX/*.mp3
"""

import asyncio
import edge_tts
import re
import os
import sys
from pathlib import Path

BASE_DIR = Path(__file__).parent.parent
TEMAS_DIR = BASE_DIR / "src" / "main" / "resources" / "temas"
AUDIOS_DIR = BASE_DIR / "src" / "main" / "resources" / "static" / "audios"
VOZ = "es-ES-AlvaroNeural"


def limpiar_markdown(texto: str) -> str:
    texto = re.sub(r'```.*?```', ' [código] ', texto, flags=re.DOTALL)
    texto = re.sub(r'\|.*?\|', '', texto)
    texto = re.sub(r'[#*_~`>]', '', texto)
    return ' '.join(texto.split())


def extraer_titulo(path_md: Path) -> str:
    """Usa el primer encabezado ## del fichero como título del MP3."""
    for linea in path_md.read_text(encoding="utf-8").splitlines():
        linea = linea.strip()
        if linea.startswith('## '):
            return linea[3:].strip()
    return path_md.stem.replace('_', ' ').capitalize()


async def convertir(path_md: Path, mp3_dir: Path) -> None:
    mp3_dir.mkdir(parents=True, exist_ok=True)
    final_output = mp3_dir / path_md.with_suffix('.mp3').name
    temp_output = mp3_dir / (path_md.stem + '.temp.mp3')

    if final_output.exists() and final_output.stat().st_mtime >= path_md.stat().st_mtime:
        print(f"⏭️  Sin cambios, omitiendo: {path_md.name}")
        return

    titulo = extraer_titulo(path_md)
    titulo_escaped = titulo.replace('"', '\\"')

    texto = path_md.read_text(encoding="utf-8")
    texto_limpio = limpiar_markdown(texto)

    print(f"🔊 Generando: {path_md.name}  ({len(texto_limpio)} caracteres)...")
    comunicar = edge_tts.Communicate(texto_limpio, VOZ)
    await comunicar.save(str(temp_output))

    comando = (
        f'ffmpeg -i "{temp_output}" -codec:a libmp3lame -b:a 192k -ar 44100 '
        f'-metadata title="{titulo_escaped}" -id3v2_version 3 -write_id3v1 1 '
        f'-y "{final_output}" > /dev/null 2>&1'
    )
    os.system(comando)

    if temp_output.exists():
        temp_output.unlink()

    print(f"✅ Listo: {final_output.relative_to(BASE_DIR)}")


def resolver_archivos(args: list[str]) -> list[tuple[Path, Path]]:
    """
    Devuelve lista de (path_md, mp3_dir).
    - Sin args: todos los bloques.
    - Args numéricos: solo esos bloques (ej. '2 3').
    - Args con ruta de fichero: ese fichero concreto.
    """
    resultado = []

    if not args:
        bloques = range(1, 5)
    else:
        bloques_num = []
        ficheros_directos = []
        for a in args:
            if re.fullmatch(r'\d', a):
                bloques_num.append(int(a))
            else:
                ficheros_directos.append(Path(a))

        for path_md in ficheros_directos:
            match = re.search(r'bloque(\d+)', str(path_md))
            bloque_num = match.group(1) if match else 'misc'
            resultado.append((path_md, AUDIOS_DIR / f"bloque{bloque_num}"))

        bloques = bloques_num

    for n in bloques:
        md_dir = TEMAS_DIR / f"bloque{n}"
        mp3_dir = AUDIOS_DIR / f"bloque{n}"
        if not md_dir.exists():
            print(f"⚠️  No existe: {md_dir}")
            continue
        for path_md in sorted(md_dir.glob('*_audio.md')):
            resultado.append((path_md, mp3_dir))

    return resultado


async def main() -> None:
    archivos = resolver_archivos(sys.argv[1:])
    if not archivos:
        print("No se encontraron ficheros *_audio.md.")
        return

    print(f"📂 Procesando {len(archivos)} fichero(s)...\n")
    for path_md, mp3_dir in archivos:
        await convertir(path_md, mp3_dir)

    print("\n✨ Proceso completado.")


if __name__ == "__main__":
    asyncio.run(main())
