from __future__ import annotations

import os
from typing import Any, Mapping
from urllib.parse import urlsplit, urlunsplit

AZURE_SPEECH_TTS_SAMPLE_RATE = 16_000


def _pick(*values: Any) -> str:
    for value in values:
        if value is None:
            continue
        text = str(value).strip()
        if text:
            return text
    return ""


def _normalize_speech_endpoint(value: str) -> str:
    endpoint = (value or "").strip()
    if not endpoint:
        return ""

    parsed = urlsplit(endpoint)
    path = (parsed.path or "").strip().rstrip("/")
    host = (parsed.hostname or "").strip().lower()
    is_custom_domain = host.endswith(".cognitiveservices.azure.com")

    if path in {"", "/"}:
        path = "/cognitiveservices/v1"

    if is_custom_domain and path == "/cognitiveservices/v1":
        path = "/tts/cognitiveservices/v1"

    return urlunsplit(parsed._replace(path=path)).rstrip("/")


def _is_custom_domain_tts_endpoint(value: str) -> bool:
    endpoint = (value or "").strip()
    if not endpoint:
        return False

    parsed = urlsplit(endpoint)
    host = (parsed.hostname or "").strip().lower()
    path = (parsed.path or "").rstrip("/")
    return host.endswith(".cognitiveservices.azure.com") and path in {
        "/cognitiveservices/v1",
        "/tts/cognitiveservices/v1",
    }


def resolve_azure_speech_tts_config(
    tts_overrides: Mapping[str, Any] | None = None,
    *,
    environ: Mapping[str, str] | None = None,
) -> tuple[dict[str, str | None], list[str]]:
    overrides = dict(tts_overrides or {})
    env = os.environ if environ is None else environ

    speech_key = _pick(env.get("AZURE_SPEECH_KEY"))
    speech_auth_token = _pick(env.get("AZURE_SPEECH_AUTH_TOKEN"))
    speech_region = _pick(env.get("AZURE_SPEECH_REGION"))
    speech_endpoint = _normalize_speech_endpoint(
        _pick(env.get("AZURE_SPEECH_ENDPOINT"), env.get("AZURE_SPEECH_HOST"))
    )
    voice = _pick(overrides.get("voice"), overrides.get("voice_id"), env.get("AZURE_SPEECH_VOICE"))
    language = _pick(overrides.get("language"), env.get("AZURE_SPEECH_LANGUAGE"))
    deployment_id = _pick(
        overrides.get("deployment_id"),
        overrides.get("model_id"),
        env.get("AZURE_SPEECH_DEPLOYMENT_ID"),
    )

    missing: list[str] = []
    if not voice:
        missing.append("AZURE_SPEECH_VOICE")
    if not (speech_endpoint or speech_region):
        missing.append("AZURE_SPEECH_ENDPOINT|AZURE_SPEECH_HOST|AZURE_SPEECH_REGION")
    if not (speech_key or speech_auth_token):
        missing.append("AZURE_SPEECH_KEY|AZURE_SPEECH_AUTH_TOKEN")

    if missing:
        return {}, missing

    if speech_endpoint and deployment_id:
        parsed = urlsplit(speech_endpoint)
        if (parsed.path or "").rstrip("/") == "/tts/cognitiveservices/v1":
            speech_endpoint = urlunsplit(
                parsed._replace(path="/voice/cognitiveservices/v1")
            ).rstrip("/")

    return (
        {
            "voice": voice,
            "language": language or None,
            "speech_key": speech_key or None,
            "speech_region": speech_region or None,
            "speech_endpoint": speech_endpoint or None,
            "deployment_id": deployment_id or None,
            "speech_auth_token": speech_auth_token or None,
        },
        [],
    )
