"""영상 비주얼 생성 — Windows GPU 서버 (NVENC) 호출.

Windows 서버 다운/실패 시 즉시 예외 (NAS 로컬 폴백 없음 — 의도적 결정).
"""
import os
import logging
import httpx

from . import storage

logger = logging.getLogger("music-lab.video")

ENCODER_URL = os.getenv("WINDOWS_VIDEO_ENCODER_URL", "")
ENCODER_TIMEOUT_BASE_S = 300  # 짧은 영상용 base


def _encoder_timeout(duration_sec: int) -> int:
    """duration에 비례한 HTTP timeout — Windows ffmpeg timeout (~0.3x duration + 180)에 60s 마진 추가.

    1분 → 300s, 30분 → 780s, 60분 → 1320s, 120분 → 2400s
    """
    return max(ENCODER_TIMEOUT_BASE_S, int(duration_sec * 0.3) + 240)

# NAS 호스트 절대경로 prefix — docker bind mount의 host 측
NAS_VIDEOS_ROOT = os.getenv("NAS_VIDEOS_ROOT", "/volume1/docker/webpage/data/videos")
NAS_MUSIC_ROOT = os.getenv("NAS_MUSIC_ROOT", "/volume1/docker/webpage/data/music")


class VideoGenerationError(Exception):
    pass


def generate(*, pipeline_id: int, audio_path: str, cover_path: str,
             genre: str, duration_sec: int, resolution: str = "1920x1080",
             style: str = "essential",
             background_mode: str = "static",
             background_path: str | None = None,
             tracks: list[dict] | None = None) -> dict:
    """원격 Windows GPU 서버 호출. 다운/실패 시 즉시 예외."""
    if not ENCODER_URL:
        raise VideoGenerationError(
            "WINDOWS_VIDEO_ENCODER_URL 미설정 — Windows 인코더 서버 주소 필요"
        )

    out_path = os.path.join(storage.pipeline_dir(pipeline_id), "video.mp4")
    nas_audio = _container_to_nas(audio_path)
    nas_cover = _container_to_nas(cover_path)
    nas_output = _container_to_nas(out_path)
    nas_bg = _container_to_nas(background_path) if background_path else None

    payload = {
        "cover_path_nas": nas_cover,
        "audio_path_nas": nas_audio,
        "output_path_nas": nas_output,
        "resolution": resolution,
        "duration_sec": duration_sec,
        "style": style,
        "background_mode": background_mode,
        "background_path_nas": nas_bg,
        "tracks": tracks or [],
    }

    timeout_s = _encoder_timeout(duration_sec)
    logger.info("Windows 인코더 호출 (timeout=%ds): pipeline=%d duration=%ds style=%s bg_mode=%s",
                 timeout_s, pipeline_id, duration_sec, style, background_mode)
    try:
        with httpx.Client(timeout=timeout_s) as client:
            resp = client.post(f"{ENCODER_URL}/encode_video", json=payload)
    except (httpx.ConnectError, httpx.ReadTimeout, httpx.WriteTimeout, httpx.NetworkError) as e:
        raise VideoGenerationError(f"Windows 인코더 연결 실패: {e}")

    if resp.status_code != 200:
        try:
            body = resp.json()
            # FastAPI HTTPException wraps in {"detail": ...}
            detail = body.get("detail", body) if isinstance(body, dict) else body
        except Exception:
            detail = {"error": resp.text[:300]}
        if isinstance(detail, dict):
            stage = detail.get("stage", "?")
            error = detail.get("error", str(detail))
        else:
            stage = "?"
            error = str(detail)
        raise VideoGenerationError(
            f"Windows 인코더 오류 ({resp.status_code}): {stage} — {error}"
        )

    data = resp.json()
    if not data.get("ok"):
        raise VideoGenerationError(f"Windows 인코더 응답 ok=false: {data}")

    return {
        "url": storage.media_url(pipeline_id, "video.mp4"),
        "used_fallback": False,
        "duration_sec": duration_sec,
        "encode_duration_ms": data.get("duration_ms"),
        "encoder": data.get("encoder", "h264_nvenc"),
    }


def _container_to_nas(container_path: str) -> str:
    """ /app/data/videos/3/cover.jpg → /volume1/docker/webpage/data/videos/3/cover.jpg
        /app/data/abc.mp3            → /volume1/docker/webpage/data/music/abc.mp3
    """
    if not container_path:
        return ""
    # Strip query string (e.g., cache-buster ?v=...)
    container_path = container_path.split("?", 1)[0]
    if container_path.startswith("/app/data/videos/"):
        return container_path.replace("/app/data/videos/", NAS_VIDEOS_ROOT + "/", 1)
    if container_path.startswith("/app/data/"):
        rel = container_path[len("/app/data/"):]
        return NAS_MUSIC_ROOT + "/" + rel
    return container_path
