"""FikoYT Edge TTS — Microsoft Edge bulut TTS (20 ses, ücretsiz)."""
import os
import asyncio
import tempfile

import torch


EDGE_VOICES = [
    # Türkçe
    "tr-TR-EmelNeural",
    "tr-TR-AhmetNeural",
    # İngilizce (US)
    "en-US-JennyNeural",
    "en-US-AriaNeural",
    "en-US-GuyNeural",
    "en-US-DavisNeural",
    # İngilizce (GB)
    "en-GB-SoniaNeural",
    "en-GB-RyanNeural",
    # Almanca
    "de-DE-KatjaNeural",
    "de-DE-ConradNeural",
    # Fransızca
    "fr-FR-DeniseNeural",
    "fr-FR-HenriNeural",
    # İspanyolca
    "es-ES-ElviraNeural",
    "es-ES-AlvaroNeural",
    # Arapça
    "ar-SA-ZariyahNeural",
    "ar-SA-HamedNeural",
    # Japonca
    "ja-JP-NanamiNeural",
    "ja-JP-KeitaNeural",
    # Korece
    "ko-KR-SunHiNeural",
    "ko-KR-InJoonNeural",
]


def _fmt_pct(v: int) -> str:
    sign = "+" if v >= 0 else ""
    return f"{sign}{int(v)}%"


def _fmt_hz(v: int) -> str:
    sign = "+" if v >= 0 else ""
    return f"{sign}{int(v)}Hz"


class FikoYTEdgeTTS:
    @classmethod
    def INPUT_TYPES(cls):
        return {
            "required": {
                "text": ("STRING", {"multiline": True, "default": "Merhaba, bu Edge TTS testidir."}),
                "voice": (EDGE_VOICES, {"default": "tr-TR-AhmetNeural"}),
                "rate": ("INT", {"default": 0, "min": -50, "max": 50, "step": 1}),
                "pitch": ("INT", {"default": 0, "min": -50, "max": 50, "step": 1}),
            }
        }

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

    def synthesize(self, text, voice, rate, pitch):
        try:
            import edge_tts
        except ImportError:
            raise RuntimeError(
                "edge-tts paketi kurulu değil.\nKurulum: pip install edge-tts"
            )

        fd, mp3_path = tempfile.mkstemp(suffix=".mp3", prefix="fikoyt_edge_")
        os.close(fd)

        async def _run():
            communicate = edge_tts.Communicate(
                text=text,
                voice=voice,
                rate=_fmt_pct(rate),
                pitch=_fmt_hz(pitch),
            )
            await communicate.save(mp3_path)

        try:
            try:
                asyncio.get_running_loop()
            except RuntimeError:
                asyncio.run(_run())
            else:
                import concurrent.futures
                with concurrent.futures.ThreadPoolExecutor(1) as ex:
                    ex.submit(asyncio.run, _run()).result()

            # MP3 → tensor (torchaudio backend handles mp3 via ffmpeg/soundfile/mp3)
            import torchaudio
            try:
                wav, sr = torchaudio.load(mp3_path)
            except Exception:
                # Fallback: pydub → wav
                from pydub import AudioSegment
                seg = AudioSegment.from_mp3(mp3_path)
                wav_path = mp3_path.replace(".mp3", ".wav")
                seg.export(wav_path, format="wav")
                wav, sr = torchaudio.load(wav_path)
                try: os.remove(wav_path)
                except: pass

            if wav.dim() == 2:
                wav = wav.unsqueeze(0)
            print(f"[FikoYT EdgeTTS] {voice} {wav.shape[-1]/sr:.1f}s @ {sr}Hz")
            return ({"waveform": wav.float(), "sample_rate": int(sr)},)
        finally:
            try:
                if os.path.isfile(mp3_path):
                    os.remove(mp3_path)
            except Exception:
                pass


NODE_CLASS_MAPPINGS = {"FikoYTEdgeTTS": FikoYTEdgeTTS}
NODE_DISPLAY_NAME_MAPPINGS = {"FikoYTEdgeTTS": "FikoYT • Edge TTS (20 ses)"}
