"""LiveKit RoomCompositeEgress helpers for Story 9 call recordings.

Requires:
  LIVEKIT_URL, LIVEKIT_API_KEY, LIVEKIT_API_SECRET
  LIVEKIT_EGRESS_S3_BUCKET, LIVEKIT_EGRESS_S3_REGION
  LIVEKIT_EGRESS_S3_ACCESS_KEY, LIVEKIT_EGRESS_S3_SECRET
Optional:
  LIVEKIT_EGRESS_S3_ENDPOINT  (for non-AWS S3-compatible stores)
  LIVEKIT_EGRESS_ENABLED      (default: on when S3 bucket is set)
"""

from __future__ import annotations

import logging
import os
import time
from typing import Any

logger = logging.getLogger("voice-livekit.recording")


def egress_configured() -> bool:
    flag = (os.environ.get("LIVEKIT_EGRESS_ENABLED") or "").strip().lower()
    if flag in ("0", "false", "no", "off"):
        return False
    if flag in ("1", "true", "yes", "on"):
        return True
    return bool(os.environ.get("LIVEKIT_EGRESS_S3_BUCKET"))


def _s3_upload():
    from livekit import api

    bucket = os.environ.get("LIVEKIT_EGRESS_S3_BUCKET", "").strip()
    if not bucket:
        raise ValueError("LIVEKIT_EGRESS_S3_BUCKET not set")

    kwargs: dict[str, Any] = {
        "access_key": os.environ.get("LIVEKIT_EGRESS_S3_ACCESS_KEY", ""),
        "secret": os.environ.get("LIVEKIT_EGRESS_S3_SECRET", ""),
        "region": os.environ.get("LIVEKIT_EGRESS_S3_REGION", "us-east-1"),
        "bucket": bucket,
    }
    endpoint = (os.environ.get("LIVEKIT_EGRESS_S3_ENDPOINT") or "").strip()
    if endpoint:
        kwargs["endpoint"] = endpoint
    force_path = (os.environ.get("LIVEKIT_EGRESS_S3_FORCE_PATH_STYLE") or "").lower()
    if force_path in ("1", "true", "yes", "on"):
        kwargs["force_path_style"] = True
    return api.S3Upload(**kwargs)


async def start_room_recording(room_name: str, call_id: str) -> dict[str, Any] | None:
    """Start audio-only RoomCompositeEgress. Returns {egress_id, filepath} or None."""
    if not egress_configured():
        logger.info("egress not configured — skipping recording for room=%s", room_name)
        return None

    try:
        from livekit import api
    except ImportError:
        logger.warning("livekit-api not installed — skipping recording")
        return None

    filepath = f"recordings/{call_id}-{int(time.time())}.ogg"
    try:
        lkapi = api.LiveKitAPI()
        req = api.RoomCompositeEgressRequest(
            room_name=room_name,
            audio_only=True,
            file_outputs=[
                api.EncodedFileOutput(
                    file_type=api.EncodedFileType.OGG,
                    filepath=filepath,
                    s3=_s3_upload(),
                )
            ],
        )
        info = await lkapi.egress.start_room_composite_egress(req)
        await lkapi.aclose()
        egress_id = getattr(info, "egress_id", None) or getattr(info, "egressId", None)
        logger.info("started egress id=%s room=%s file=%s", egress_id, room_name, filepath)
        return {"egress_id": egress_id, "filepath": filepath, "started_at": time.time()}
    except Exception as e:  # noqa: BLE001
        logger.warning("failed to start egress for room=%s: %s", room_name, e)
        return None


def _extract_file_url(info: Any) -> str | None:
    """Best-effort extract of the uploaded file location from StopEgress / GetEgress."""
    # Newer SDKs: info.file.location or info.file_results
    file_obj = getattr(info, "file", None)
    if file_obj is not None:
        loc = getattr(file_obj, "location", None) or getattr(file_obj, "filename", None)
        if loc:
            return str(loc)

    results = getattr(info, "file_results", None) or getattr(info, "fileResults", None) or []
    for fr in results:
        loc = getattr(fr, "location", None) or getattr(fr, "filename", None)
        if loc:
            return str(loc)
        if isinstance(fr, dict):
            loc = fr.get("location") or fr.get("filename")
            if loc:
                return str(loc)

    # Fallback: build virtual-hosted S3 URL from filepath if present on result.
    return None


def _s3_public_url(filepath: str) -> str | None:
    bucket = os.environ.get("LIVEKIT_EGRESS_S3_BUCKET", "").strip()
    region = os.environ.get("LIVEKIT_EGRESS_S3_REGION", "us-east-1").strip()
    endpoint = (os.environ.get("LIVEKIT_EGRESS_S3_ENDPOINT") or "").strip()
    if not bucket or not filepath:
        return None
    if endpoint:
        return f"{endpoint.rstrip('/')}/{bucket}/{filepath.lstrip('/')}"
    return f"https://{bucket}.s3.{region}.amazonaws.com/{filepath.lstrip('/')}"


async def stop_room_recording(egress_state: dict[str, Any] | None) -> dict[str, Any]:
    """Stop egress and resolve recording URL + duration.

    Returns {recording_url?, duration_seconds?, error?}.
    """
    if not egress_state or not egress_state.get("egress_id"):
        return {}

    try:
        from livekit import api
    except ImportError:
        return {"error": "livekit-api not installed"}

    egress_id = egress_state["egress_id"]
    filepath = egress_state.get("filepath") or ""
    started_at = float(egress_state.get("started_at") or time.time())
    duration = max(0.0, time.time() - started_at)

    try:
        lkapi = api.LiveKitAPI()
        info = await lkapi.egress.stop_egress(api.StopEgressRequest(egress_id=egress_id))
        await lkapi.aclose()
        url = _extract_file_url(info) or _s3_public_url(filepath)
        logger.info("stopped egress id=%s url=%s duration=%.1fs", egress_id, url, duration)
        return {
            "recording_url": url,
            "duration_seconds": duration,
        }
    except Exception as e:  # noqa: BLE001
        # Stop can race with room close — still try a constructed S3 URL.
        logger.warning("stop egress failed id=%s: %s", egress_id, e)
        url = _s3_public_url(filepath)
        return {
            "recording_url": url,
            "duration_seconds": duration,
            "error": str(e),
        }
