#!/usr/bin/env python3
"""Orquestador nocturno: locuta cartas ES del gap con MiniMax, una a una,
repartido en el tiempo. Voz por defecto Nico; los artículos de autores con voz
clonada (AUTHOR_VOICES en minimax_tts.py, ej. Fray Marcos) usan la suya propia.
Reanudable (meta fea_audio_done) y con freno ante la cuota (para tras N fallos
seguidos). NO toca el front; solo genera el mp3 y asocia la URL al post (meta
fea_audio_url).

Lanzar:  nohup ~/tts-local/xtts-venv/bin/python scripts/tts_produce.py > /tmp/feadulta-tts-prod.out 2>&1 &
Log:     /tmp/feadulta-tts-prod.log
"""
import os
import shutil
import subprocess
import sys
import time
from pathlib import Path

sys.path.insert(0, os.path.dirname(os.path.abspath(__file__)))
import minimax_tts as mm          # get_post_text, add_pauses, t2a, OUT
import translate_post as tp       # carta_article_ids

VOICE = "NicoFeadulta2026"
MODEL = "speech-2.8-hd"
CONTAINER = "wordpress-web"
PROD = Path(__file__).resolve().parent.parent / "wordpress/wp-content/uploads/tts"
LOG = Path("/tmp/feadulta-tts-prod.log")
INTERVAL = 180          # s entre cartas exitosas (reparte el ritmo)
BACKOFF = 1800          # s de espera ante fallo de cuota antes de reintentar
MAX_CONSEC_FAIL = 3     # fallos seguidos → parar (cuota probablemente agotada)
MIN_CHARS = 200         # por debajo, se considera sin contenido locutable

# Cola de cartas a locutar. Override por entorno (FEA_TTS_CARTAS) para priorizar
# la carta nueva de la semana; si no, cae al orden del gap histórico.
_DEFAULT_CARTAS = "45018 44997 44975 44230 44229 44228 44090 44089 44088 44087 44086 44085 44084 44083 42590"
CARTAS = os.environ.get("FEA_TTS_CARTAS", _DEFAULT_CARTAS).replace(",", " ").split()


def log(msg):
    line = f"[{time.strftime('%Y-%m-%d %H:%M:%S')}] {msg}"
    print(line, flush=True)
    with LOG.open("a") as f:
        f.write(line + "\n")


def php(*args):
    return subprocess.run(["docker", "exec", CONTAINER, "php", "/tmp/fea_post_io.php", *args],
                          capture_output=True, text=True)


def meta(pid, key):
    return php("getmeta", str(pid), key).stdout.strip()


def build_queue():
    # Cola literal de IDs (ya filtrada/ordenada) para priorizar la carta nueva.
    ids_override = os.environ.get("FEA_TTS_IDS", "").replace(",", " ").split()
    if ids_override:
        return [int(x) for x in ids_override if x.strip().isdigit()]
    q = []
    for c in CARTAS:
        cid = int(c)
        for pid in tp.carta_article_ids(cid):
            if pid not in q:
                q.append(pid)
    return q


def main():
    PROD.mkdir(parents=True, exist_ok=True)
    subprocess.run(["docker", "cp", "scripts/fea_post_io.php", f"{CONTAINER}:/tmp/fea_post_io.php"],
                   capture_output=True)
    queue = build_queue()
    log(f"=== INICIO orquestador TTS. Cola: {len(queue)} posts ES del gap ===")

    i = consec = ok = 0
    while i < len(queue):
        pid = queue[i]
        if meta(pid, "fea_audio_done") == "1" or meta(pid, "fea_audio_skip") == "1":
            i += 1
            continue
        try:
            title, text, author = mm.get_post_text(pid)
        except Exception as e:  # noqa: BLE001
            log(f"#{pid}: error leyendo ({e}); skip")
            php("setflag", str(pid), "fea_audio_skip", "1")
            i += 1
            continue
        if len(text) < MIN_CHARS:
            log(f"#{pid}: sin contenido ({len(text)} car); skip")
            php("setflag", str(pid), "fea_audio_skip", "1")
            i += 1
            continue

        voice = mm.voice_for_author(author, VOICE)
        rc = mm.t2a(mm.add_pauses(text), voice, MODEL, f"prod-{pid}")
        if rc == 0:
            src = mm.OUT / f"prod-{pid}.mp3"
            dst = PROD / f"{pid}.mp3"
            shutil.move(str(src), str(dst))
            php("setaudio", str(pid), f"/wp-content/uploads/tts/{pid}.mp3", voice)
            ok += 1
            consec = 0
            voice_tag = f" [{voice}]" if voice != VOICE else ""
            log(f"#{pid} OK «{title[:45]}»{voice_tag} → tts/{pid}.mp3  (total {ok})")
            i += 1
            time.sleep(INTERVAL)
        else:
            consec += 1
            log(f"#{pid} FALLO rc={rc} (fallo seguido {consec}/{MAX_CONSEC_FAIL})")
            php("setflag", str(pid), "fea_audio_error", str(rc))
            if consec >= MAX_CONSEC_FAIL:
                log("Demasiados fallos seguidos → cuota agotada probablemente. PARO. "
                    "Reanudable: relanzar el script más tarde (salta lo ya hecho).")
                break
            time.sleep(BACKOFF)   # reintenta el mismo post tras esperar

    log(f"=== FIN tanda. {ok} audios generados esta ejecución. ===")


if __name__ == "__main__":
    main()
