from __future__ import annotations

import json
import os
import ssl
from dataclasses import dataclass
from pathlib import Path
from urllib.error import HTTPError, URLError
from urllib.parse import urljoin
from urllib.request import Request, urlopen

import numpy as np

from core.audio.wav_for_whisper import try_load_wav_for_faster_whisper
from core.logging_config import get_logger

logger = get_logger(__name__)

#DEFAULT_SERVER_URL = "http://127.0.0.1:8000"
DEFAULT_SERVER_URL = "https://vifon.boskar.net"
TRANSCRIPTION_ENDPOINT = "/v1/audio/transcriptions"
TARGET_SAMPLE_RATE = 16000


@dataclass
class HttpTranscriptionResponse:
    text: str
    language: str | None
    duration: float | None


def _server_url() -> str:
    return os.environ.get("CLI_SERVER_URL", DEFAULT_SERVER_URL).rstrip("/")


def _timeout_seconds() -> float:
    value = os.environ.get("CLI_SERVER_TIMEOUT", "300")
    try:
        return float(value)
    except ValueError:
        return 300.0


def _load_audio(path: str | Path) -> tuple[np.ndarray, int]:
    wav_audio = try_load_wav_for_faster_whisper(path, target_sr=TARGET_SAMPLE_RATE)
    if wav_audio is not None:
        return wav_audio.astype(np.float32, copy=False), TARGET_SAMPLE_RATE

    from faster_whisper.audio import decode_audio

    audio = decode_audio(str(path), sampling_rate=TARGET_SAMPLE_RATE)
    return audio.astype(np.float32, copy=False), TARGET_SAMPLE_RATE


def transcribe_via_cli_server(
    audio_file: str | Path,
    *,
    timeout: float | None = None,
) -> HttpTranscriptionResponse:
    timeout = _timeout_seconds() if timeout is None else timeout
    audio, sample_rate = _load_audio(audio_file)
    payload = json.dumps(
        {
            "audio": audio.tolist(),
            "sample_rate": sample_rate,
        }
    ).encode("utf-8")

    payload_mb = len(payload) / (1024 * 1024)
    logger.info(
        "Sending audio to cli-server.py: url=%s payload=%.2fMB timeout=%.0fs",
        urljoin(_server_url() + "/", TRANSCRIPTION_ENDPOINT.lstrip("/")),
        payload_mb,
        timeout,
    )

    url = urljoin(_server_url() + "/", TRANSCRIPTION_ENDPOINT.lstrip("/"))
    request = Request(
        url,
        data=payload,
        headers={
            "Content-Type": "application/json",
            "Content-Length": str(len(payload)),
            "User-Agent": "Faster-Whisper-Transcriber/cli-server-client",
        },
        method="POST",
    )

    try:
        with urlopen(request, timeout=timeout, context=ssl._create_unverified_context()) as response:
            body = response.read().decode("utf-8")
    except HTTPError as exc:
        detail = exc.read().decode("utf-8", errors="replace")
        raise RuntimeError(f"cli-server.py returned HTTP {exc.code}: {detail}") from exc
    except URLError as exc:
        raise RuntimeError(f"Cannot connect to cli-server.py at {_server_url()}: {exc.reason}") from exc

    data = json.loads(body)
    text = str(data.get("text", ""))
    language = data.get("language")
    duration = float(audio.shape[0]) / sample_rate if sample_rate > 0 else None
    return HttpTranscriptionResponse(
        text=text,
        language=language,
        duration=duration,
    )
