"""FikoYT F5-TTS — doğal zero-shot ses klonlama (F5-TTS + vocos)."""
import os
import tempfile
import torch

try:
    import folder_paths
except ImportError:
    folder_paths = None

from ..core import get_models_dir


_MAX_REF_SEC = 15.0
_MODEL_CACHE = {"tts": None}


def _audio_to_tempfile(audio: dict) -> str:
    """ComfyUI AUDIO → temp WAV path. MP3 olsa bile pydub gerekmiyor — tensor zaten waveform."""
    import torchaudio
    wav = audio["waveform"]
    sr = int(audio["sample_rate"])
    # [1, C, S] → [C, S]
    if wav.dim() == 3:
        wav = wav.squeeze(0)
    if wav.dim() == 1:
        wav = wav.unsqueeze(0)

    # 15s'den uzunsa kırp
    max_samples = int(_MAX_REF_SEC * sr)
    if wav.shape[-1] > max_samples:
        wav = wav[..., :max_samples]
        print(f"[FikoYT F5-TTS] Referans {wav.shape[-1]/sr:.1f}s → {_MAX_REF_SEC}s kırpıldı")

    fd, path = tempfile.mkstemp(suffix=".wav", prefix="fikoyt_f5_ref_")
    os.close(fd)
    torchaudio.save(path, wav.cpu().float(), sr)
    return path


def _wav_path_to_audio(path: str) -> dict:
    import torchaudio
    wav, sr = torchaudio.load(path)
    # → [1, C, S]
    if wav.dim() == 2:
        wav = wav.unsqueeze(0)
    return {"waveform": wav, "sample_rate": int(sr)}


class FikoYTF5TTS:
    @classmethod
    def INPUT_TYPES(cls):
        return {
            "required": {
                "text": ("STRING", {"multiline": True, "default": "Merhaba, bu bir test seslendirmesidir."}),
                "reference_audio": ("AUDIO",),
                "reference_text": ("STRING", {"multiline": True, "default": ""}),
                "speed": ("FLOAT", {"default": 1.0, "min": 0.5, "max": 2.0, "step": 0.05}),
                "max_chunk_sec": ("FLOAT", {"default": 15.0, "min": 5.0, "max": 30.0, "step": 1.0}),
                "remove_silence": ("BOOLEAN", {"default": True}),
                "auto_download": ("BOOLEAN", {"default": True}),
            }
        }

    RETURN_TYPES = ("AUDIO",)
    RETURN_NAMES = ("audio",)
    FUNCTION = "synthesize"
    CATEGORY = "FikoYT/audio"

    def synthesize(self, text, reference_audio, reference_text, speed,
                   max_chunk_sec, remove_silence, auto_download):
        try:
            from f5_tts.api import F5TTS
        except ImportError:
            raise RuntimeError(
                "f5-tts paketi kurulu değil.\n"
                "Kurulum: pip install f5-tts\n"
                "(vocos vocoder ilk çağrıda otomatik iner)"
            )

        ref_path = _audio_to_tempfile(reference_audio)
        try:
            # Auto-transcribe if ref_text empty
            _ref_txt = (reference_text or "").strip()
            if not _ref_txt:
                try:
                    import whisper as _wh
                    print("[FikoYT F5-TTS] ref_text boş, Whisper-base ile transkript…")
                    _wmod = _wh.load_model("base")
                    _res = _wmod.transcribe(ref_path, language=None)
                    _ref_txt = (_res.get("text") or "").strip()
                    del _wmod
                except Exception:
                    _ref_txt = ""

            if _MODEL_CACHE["tts"] is None:
                device = "cuda" if torch.cuda.is_available() else "cpu"
                print(f"[FikoYT F5-TTS] F5TTS yükleniyor (device={device})…")
                _MODEL_CACHE["tts"] = F5TTS(device=device)
            tts = _MODEL_CACHE["tts"]

            print(f"[FikoYT F5-TTS] üretim: speed={speed} text='{text[:60]}…'")
            kwargs = dict(ref_file=ref_path, ref_text=_ref_txt, gen_text=text, speed=float(speed))
            # max_chunk_sec / remove_silence parametreleri F5TTS sürümüne göre opsiyonel
            try:
                wav, sr, _ = tts.infer(
                    remove_silence=bool(remove_silence),
                    target_rms=0.1,
                    cross_fade_duration=0.15,
                    nfe_step=32,
                    cfg_strength=2.0,
                    **kwargs,
                )
            except TypeError:
                wav, sr, _ = tts.infer(**kwargs)

            # numpy/Tensor normalize
            import numpy as np
            if isinstance(wav, np.ndarray):
                wav_t = torch.from_numpy(wav.astype("float32"))
            else:
                wav_t = torch.as_tensor(wav, dtype=torch.float32)
            if wav_t.dim() == 1:
                wav_t = wav_t.unsqueeze(0)  # [C, S]
            wav_t = wav_t.unsqueeze(0)  # [1, C, S]
            print(f"[FikoYT F5-TTS] tamam: {wav_t.shape[-1]/sr:.1f}s @ {sr}Hz")
            return ({"waveform": wav_t, "sample_rate": int(sr)},)
        finally:
            try:
                if os.path.isfile(ref_path):
                    os.remove(ref_path)
            except Exception:
                pass


NODE_CLASS_MAPPINGS = {"FikoYTF5TTS": FikoYTF5TTS}
NODE_DISPLAY_NAME_MAPPINGS = {"FikoYTF5TTS": "FikoYT • F5-TTS (Voice Clone)"}
