#!/usr/bin/env python3
"""Da escala a la puntuacion de parecido: techo, suelo y donde cae el clon.

Un 0,68 no significa nada por si solo. Hace falta saber cuanto puntuan DOS
grabaciones distintas del mismo original (el techo realista: ni el propio
hablante da 1,0 consigo mismo) y cuanto puntua una voz que no tiene nada que
ver (el suelo). Entre esos dos numeros se lee si el clon esta cerca o lejos.

De paso prueba usar los mp3 ORIGINALES descargados como referencia, sin pasar
por los wav normalizados: si normalizar quito informacion, se vera aqui.

    python calibrar_parecido.py [cuda|cpu]
"""
import glob
import os
import subprocess
import sys
import tempfile
import time

import torch

DISPOSITIVO = sys.argv[1] if len(sys.argv) > 1 else "cuda"
BASE = os.path.dirname(os.path.abspath(__file__))
REF = os.path.join(BASE, "ref")
COMPARATIVA = os.path.join(BASE, "comparativa")
DESCARGAS = os.path.expanduser("~/Downloads")

os.environ.setdefault("COQUI_TOS_AGREED", "1")
LARGO = dict(gpt_cond_len=30, gpt_cond_chunk_len=6, max_ref_length=30)


def parecido(a, b):
    return float(torch.nn.functional.cosine_similarity(
        a.squeeze().float(), b.squeeze().float(), dim=0))


def a_wav(origen, destino):
    """mp3 -> wav mono 24k, sin tocar niveles."""
    subprocess.run(["ffmpeg", "-y", "-loglevel", "error", "-i", origen,
                    "-ar", "24000", "-ac", "1", destino], check=True)
    return destino


def main():
    from TTS.api import TTS
    print(f"cargando XTTS en {DISPOSITIVO}...", flush=True)
    api = TTS("tts_models/multilingual/multi-dataset/xtts_v2").to(DISPOSITIVO)
    modelo = api.synthesizer.tts_model

    def emb(rutas):
        _, e = modelo.get_conditioning_latents(audio_path=list(rutas), **LARGO)
        return e

    patron = emb([os.path.join(REF, "jarvis_lento_b.wav")])

    print("\n  TECHO — otras grabaciones del MISMO original:")
    for nombre in ("jarvis_lento_a.wav", "jarvis_ref.wav", "jarvis_ref2.wav",
                   "jarvis_ref_corto.wav"):
        ruta = os.path.join(REF, nombre)
        if os.path.exists(ruta):
            print(f"    {parecido(patron, emb([ruta])):.4f}  {nombre}")

    print("\n  SUELO — una voz que no es esa (Piper, castellano):")
    with tempfile.TemporaryDirectory() as tmp:
        piper = os.path.join(tmp, "piper.wav")
        guion = os.path.expanduser(
            "~/COFRE/CODERS/JARVIS/config/jarvis-piper.sh")
        try:
            subprocess.run([guion, piper, "Buenas noches, señor. Soy su asistente personal."],
                           check=True, capture_output=True, timeout=120)
            print(f"    {parecido(patron, emb([piper])):.4f}  piper es_ES")
        except Exception as e:
            print(f"    (no pude generar con Piper: {e})")

    print("\n  EL CLON — lo generado en comparar_ajustes.py:")
    for wav in sorted(glob.glob(os.path.join(COMPARATIVA, "*.wav"))):
        print(f"    {parecido(patron, emb([wav])):.4f}  {os.path.basename(wav)}")

    print("\n  ORIGINALES sin normalizar (mp3 de fish.audio) como referencia:")
    mp3s = sorted(glob.glob(os.path.join(DESCARGAS, "Jarvis-*.mp3")))
    if not mp3s:
        print("    (no hay mp3 en ~/Downloads)")
        return
    with tempfile.TemporaryDirectory() as tmp:
        convertidos = [a_wav(m, os.path.join(tmp, f"o{i}.wav"))
                       for i, m in enumerate(mp3s)]
        for c, m in zip(convertidos, mp3s):
            print(f"    {parecido(patron, emb([c])):.4f}  {os.path.basename(m)[:52]}")

        # y clonar usando los originales como referencia, a ver si mejora
        gpt, hablante = modelo.get_conditioning_latents(
            audio_path=convertidos, **LARGO)
        salida = modelo.inference(
            text="Buenas noches, señor. Soy su asistente personal.",
            language="es", gpt_cond_latent=gpt, speaker_embedding=hablante,
            temperature=0.65, repetition_penalty=2.0, speed=1.0,
            enable_text_splitting=True)
        import soundfile as sf
        destino = os.path.join(COMPARATIVA, "F_originales_sin_normalizar.wav")
        sf.write(destino, salida["wav"], 24000)
        print(f"\n    {parecido(patron, emb([destino])):.4f}  "
              f"F_originales_sin_normalizar.wav  (clon con los mp3 crudos)")


if __name__ == "__main__":
    main()
