import os
import re
import sys
import traceback
from io import BytesIO

import requests
from dotenv import load_dotenv


SCRIPT_DIR = os.path.dirname(os.path.abspath(__file__))
load_dotenv(os.path.join(SCRIPT_DIR, ".env"))

try:
    sys.stdout.reconfigure(encoding="utf-8")
except Exception:
    pass


def number_to_turkish(number: int) -> str:
    """0-999 arasındaki yol numaralarını TTS için yazıya çevirir."""
    ones = ["sıfır", "bir", "iki", "üç", "dört", "beş", "altı", "yedi", "sekiz", "dokuz"]
    tens = ["", "on", "yirmi", "otuz", "kırk", "elli", "altmış", "yetmiş", "seksen", "doksan"]

    if number < 10:
        return ones[number]
    if number < 100:
        return " ".join(
            part
            for part in (tens[number // 10], ones[number % 10] if number % 10 else "")
            if part
        )

    hundreds = "yüz" if number // 100 == 1 else f"{ones[number // 100]} yüz"
    remainder = number % 100
    return hundreds if remainder == 0 else f"{hundreds} {number_to_turkish(remainder)}"


def road_number_for_speech(match: re.Match) -> str:
    prefix = match.group(1).upper()
    number = number_to_turkish(int(match.group(2)))
    return f"Otoyol {number}" if prefix == "O" else f"{prefix} {number}"


def normalize_sentence(sentence: str) -> str:
    """Yol isimlerini TTS için daha doğal okunacak hâle getirir."""
    sentence = re.sub(r"(\d+)[\.,]\d+", lambda match: match.group(1), sentence)
    sentence = sentence.replace("İstanbul–Ankara", "İstanbul Ankara")
    sentence = sentence.replace("Ankara–Konya", "Ankara Konya")
    sentence = sentence.replace("Ankara–İstanbul", "Ankara İstanbul")
    sentence = sentence.replace("İstanbul–İzmir", "İstanbul İzmir")
    sentence = sentence.replace("İzmir–Aydın", "İzmir Aydın")
    sentence = sentence.replace("Antalya–Burdur", "Antalya Burdur")
    sentence = sentence.replace("Antalya–Konya", "Antalya Konya")
    sentence = sentence.replace("Adana–Mersin", "Adana Mersin")
    sentence = re.sub(
        r"\b([DOE])[-–\s]?(\d{1,3})\b",
        road_number_for_speech,
        sentence,
        flags=re.IGNORECASE,
    )
    sentence = re.sub(r"\s*/\s*", " ve ", sentence)
    sentence = re.sub(r"\s+", " ", sentence).strip()
    return sentence


def create_voice(text: str) -> BytesIO:
    api_key = os.getenv("ELEVENLABS_API_KEY")
    voice_id = (
        os.getenv("VOICE_MERCEDES")
        or os.getenv("VOICE_ID3")
        or os.getenv("VOICE_ID")
    )

    if not api_key:
        raise RuntimeError("ELEVENLABS_API_KEY tanımlı değil.")
    if not voice_id:
        raise RuntimeError("VOICE_MERCEDES, VOICE_ID3 veya VOICE_ID tanımlı değil.")

    response = requests.post(
        f"https://api.elevenlabs.io/v1/text-to-speech/{voice_id}",
        headers={
            "xi-api-key": api_key,
            "Content-Type": "application/json",
        },
        json={
            "text": text,
            "model_id": "eleven_v3",
            "languages": [{"language_id": "tr", "name": "Turkish"}],
            "voice_settings": {
                "stability": 0.65,
                "similarity_boost": 0.75,
                "style": 0.35,
                "speaker_boost": True,
                "speed": 0.92,
            },
            "pronunciation_guide": {
                "style": "profesyonel ve güven veren radyo spikeri, ağır vasıta yol durumu bülteni",
                "hints": (
                    "Metni sakin, net ve kontrollü oku. Yol ve trafik bilgisini haber verir gibi aktar. "
                    "Güzergâh adlarında kısa ve doğal duraklar bırak. "
                    "'Bolu Dağı', 'D yüz', 'Otoyol yedi', 'Ankara yönünde' ve "
                    "'Mercedes-Benz Trucks' ifadelerini anlaşılır ve doğru telaffuz et. "
                    "Son cümleyi marka imzası olarak güven veren, sakin bir tonla bitir. "
                    "Metne yeni kelime veya açıklama ekleme."
                ),
            },
        },
        timeout=60,
    )

    if response.status_code >= 400:
        raise RuntimeError(
            f"ElevenLabs HTTP {response.status_code}: {response.text[:500]}"
        )

    return BytesIO(response.content)


def main() -> None:
    log_file = os.path.join(SCRIPT_DIR, "mercedes_py.log")

    try:
        if len(sys.argv) < 3:
            raise ValueError(
                "Kullanım: python mercedes.py <sentence> <output_path>"
            )

        sentence = normalize_sentence(sys.argv[1])
        output_path = sys.argv[2]

        print(f"Mercedes metni: {sentence}")
        print(f"Çıkış: {output_path}")

        audio_stream = create_voice(sentence)
        output_dir = os.path.dirname(os.path.abspath(output_path))
        os.makedirs(output_dir, exist_ok=True)

        with open(output_path, "wb") as output_file:
            output_file.write(audio_stream.read())

        print(f"OK: Mercedes yol durumu sesi yazıldı -> {output_path}")

    except Exception as error:
        error_text = f"ERROR (mercedes): {error}\n{traceback.format_exc()}"
        try:
            with open(log_file, "a", encoding="utf-8") as log:
                log.write("\n" + ("-" * 60) + "\n")
                log.write(error_text + "\n")
        except Exception:
            pass

        print(error_text)
        raise SystemExit(1)


if __name__ == "__main__":
    main()
