#!/usr/bin/env python3
"""¿El clon falla porque las frases son cortas?

La referencia son 25 segundos de habla seguida. Lo que JARVIS dice de verdad
son acuses de segundo y medio: "Voy, señor". XTTS arranca cada generacion sin
contexto, y en frase corta no le da tiempo a asentar la voz antes de terminar.
Si es eso, el parecido deberia subir con la longitud del texto — y la solucion
no seria tocar parametros sino generar mas largo y recortar.

Se mide con repeticiones porque XTTS muestrea: una sola pasada por longitud
seria ruido, que es el error que ya se cometio dos veces hoy.

    python prueba_longitud.py [cuda|cpu] [repeticiones]
"""
import os
import statistics
import sys
import tempfile

import torch

DISPOSITIVO = sys.argv[1] if len(sys.argv) > 1 else "cuda"
REPES = int(sys.argv[2]) if len(sys.argv) > 2 else 4

BASE = os.path.dirname(os.path.abspath(__file__))
sys.path.insert(0, BASE)
from clonador import CONDICIONADO, GENERACION, referencias

os.environ.setdefault("COQUI_TOS_AGREED", "1")
PATRON = os.path.join(BASE, "ref", "jarvis_lento_b.wav")
MEDIR = dict(gpt_cond_len=30, gpt_cond_chunk_len=6, max_ref_length=30)

# mismo registro, longitud creciente
TEXTOS = [
    ("muy corta  (~1s)", "Voy, señor."),
    ("corta      (~2s)", "Enseguida, señor. Ahora mismo."),
    ("media      (~5s)", "Enseguida, señor. He revisado el sistema y todo está en orden."),
    ("larga     (~10s)", "Enseguida, señor. He revisado el sistema y todo está en orden. "
                         "La temperatura ronda los sesenta y tres grados y quedan "
                         "cuarenta y un gigabytes de memoria libre."),
    ("muy larga (~20s)", "Enseguida, señor. He revisado el sistema y todo está en orden. "
                         "La temperatura ronda los sesenta y tres grados y quedan "
                         "cuarenta y un gigabytes de memoria libre. El disco principal "
                         "va al sesenta por ciento y no he detectado ningún proceso "
                         "anómalo. ¿Desea que ejecute el análisis de red ahora o "
                         "prefiere que espere?"),
]


def main():
    from TTS.api import TTS
    import soundfile as sf

    api = TTS("tts_models/multilingual/multi-dataset/xtts_v2").to(DISPOSITIVO)
    modelo = api.synthesizer.tts_model

    def emb(ruta):
        _, e = modelo.get_conditioning_latents(audio_path=[ruta], **MEDIR)
        return e

    patron = emb(PATRON)

    def parecido(ruta):
        return float(torch.nn.functional.cosine_similarity(
            patron.squeeze().float(), emb(ruta).squeeze().float(), dim=0))

    gpt, hablante = modelo.get_conditioning_latents(
        audio_path=referencias(), **CONDICIONADO)

    print(f"  {REPES} repeticiones por longitud · referencia a batir: 0.84-0.95\n")
    print(f"  {'texto':18s} {'dur':>6s} {'parecido':>9s} {'desv':>7s}")
    print("  " + "-" * 45)

    with tempfile.TemporaryDirectory() as tmp:
        for etiqueta, texto in TEXTOS:
            puntos, duraciones = [], []
            for r in range(REPES):
                out = modelo.inference(
                    text=texto, language="es", gpt_cond_latent=gpt,
                    speaker_embedding=hablante, enable_text_splitting=False,
                    **GENERACION)
                d = os.path.join(tmp, f"{len(puntos)}_{r}.wav")
                sf.write(d, out["wav"], 24000)
                duraciones.append(len(out["wav"]) / 24000)
                puntos.append(parecido(d))
            print(f"  {etiqueta:18s} {statistics.mean(duraciones):5.1f}s "
                  f"{statistics.mean(puntos):9.4f} {statistics.pstdev(puntos):7.4f}",
                  flush=True)


if __name__ == "__main__":
    main()
