"""Archive playback via middleware HLS proxy or Widevine MPD."""
from __future__ import annotations

import threading
from typing import Any

import xbmc
import xbmcgui

from . import logger


def _apply_start_offset(item: xbmcgui.ListItem, seek_seconds: float) -> None:
    if seek_seconds <= 0:
        return
    seek_int = int(seek_seconds)
    item.setProperty("inputstream.adaptive.start_time", str(seek_int))
    item.setProperty("inputstream.adaptive.starttime", str(seek_int))
    item.setProperty("StartOffset", str(seek_int))


def _seek_after_start(seconds: float) -> None:
    player = xbmc.Player()
    for _ in range(160):
        if player.isPlayingVideo():
            break
        xbmc.sleep(200)
    if not player.isPlayingVideo() or seconds <= 0:
        return

    for attempt in range(20):
        try:
            player.seekTime(seconds)
            xbmc.sleep(500)
            current = player.getTime()
            if current >= max(0.0, seconds - 3):
                logger.info(f"Archive seek reached {current:.0f}s (target {seconds:.0f}s)")
                return
        except RuntimeError as exc:
            logger.debug(f"Archive seek attempt {attempt + 1} failed: {exc}")
        xbmc.sleep(350)
    logger.warning(f"Archive seek may have failed; target was {seconds:.0f}s")


def _schedule_seek(seconds: float) -> None:
    if seconds <= 0:
        return
    threading.Thread(target=_seek_after_start, args=(seconds,), daemon=True).start()


def _strip_pipe_auth(url: str) -> str:
    idx = url.find("|Authorization=")
    return url[:idx] if idx >= 0 else url


def _apply_inputstream_auth(item: xbmcgui.ListItem, auth_headers: str) -> None:
    if not auth_headers:
        return
    # Pipe-auth in URLs is unsupported on inputstream.adaptive (especially Android/Kodi 21).
    item.setProperty("inputstream.adaptive.manifest_headers", auth_headers)
    item.setProperty("inputstream.adaptive.stream_headers", auth_headers)


def build_hls_item(
    playlist_url: str,
    title: str = "",
    seek_ms: int = 0,
    programme_duration_sec: int = 0,
    apply_seek: bool = True,
    auth_headers: str = "",
) -> xbmcgui.ListItem:
    playlist_url = _strip_pipe_auth(playlist_url)
    item = xbmcgui.ListItem(label=title, path=playlist_url)
    item.setProperty("inputstream", "inputstream.adaptive")
    item.setProperty("inputstream.adaptive.manifest_type", "hls")
    item.setMimeType("application/x-mpegURL")
    _apply_inputstream_auth(item, auth_headers)
    seek_seconds = max(0, int(seek_ms)) / 1000.0
    if apply_seek and seek_seconds > 0:
        _apply_start_offset(item, seek_seconds)
        _schedule_seek(seek_seconds)
    logger.info(
        f"Play HLS {playlist_url} epg_seek={seek_seconds:.0f}s apply_seek={apply_seek}"
    )
    return item


def build_widevine_item(
    play_info: dict[str, Any],
    title: str = "",
    seek_ms: int = 0,
    apply_seek: bool = True,
) -> xbmcgui.ListItem:
    stream_url = play_info.get("streamUrl") or play_info.get("stream_url", "")
    license_url = play_info.get("licenseUrl") or play_info.get("license_url", "")

    if not stream_url:
        raise ValueError("No stream URL returned")

    item = xbmcgui.ListItem(label=title, path=stream_url)
    if ".mpd" in stream_url and license_url:
        item.setProperty("inputstream", "inputstream.adaptive")
        item.setProperty("inputstream.adaptive.manifest_type", "mpd")
        item.setProperty("inputstream.adaptive.license_type", "com.widevine.alpha")
        item.setProperty("inputstream.adaptive.license_key", license_url)

    seek_seconds = seek_ms / 1000.0
    if apply_seek and seek_seconds > 0:
        _apply_start_offset(item, seek_seconds)
        _schedule_seek(seek_seconds)
    logger.info(
        f"Play stream {stream_url[:120]} epg_seek={seek_seconds:.0f}s apply_seek={apply_seek}"
    )
    return item


def build_play_item(
    play_info: dict[str, Any],
    playlist_url: str,
    title: str = "",
    resume_seconds: float = 0,
    programme_duration_sec: int = 0,
    auth_headers: str = "",
) -> xbmcgui.ListItem:
    stream_url = play_info.get("streamUrl") or play_info.get("stream_url", "")
    if resume_seconds > 0:
        # Kodi bookmark already stores the absolute stream position; do not add pre-roll.
        seek_ms = 0
        apply_seek = False
    else:
        seek_ms = int(play_info.get("seekMs") or play_info.get("seek_ms") or 0)
        apply_seek = True
    if ".m3u8" in stream_url.lower() or ".m3u8" in playlist_url.lower():
        return build_hls_item(
            playlist_url,
            title=title,
            seek_ms=seek_ms,
            programme_duration_sec=programme_duration_sec,
            apply_seek=apply_seek,
            auth_headers=auth_headers,
        )
    return build_widevine_item(
        play_info,
        title=title,
        seek_ms=seek_ms,
        apply_seek=apply_seek,
    )
