import json
from dataclasses import dataclass
from urllib.parse import parse_qs, urlencode, urlparse, urlunparse
from urllib.request import Request, urlopen


class XtreamError(Exception):
    pass


@dataclass(frozen=True)
class XtreamCredentials:
    base_url: str
    username: str
    password: str


def parse_xtream_url(value: str) -> XtreamCredentials:
    parsed = urlparse(value.strip())
    query = parse_qs(parsed.query)
    username = query.get("username", [""])[0]
    password = query.get("password", [""])[0]
    if parsed.scheme not in {"http", "https"} or not parsed.netloc:
        raise XtreamError("La URL debe comenzar con http:// o https://")
    if not username or not password:
        raise XtreamError("La URL no contiene usuario y contraseña Xtream")
    base_url = urlunparse((parsed.scheme, parsed.netloc, "", "", "", "")).rstrip("/")
    return XtreamCredentials(base_url, username, password)


class XtreamClient:
    def __init__(self, credentials: XtreamCredentials, timeout: int = 15):
        self.credentials = credentials
        self.timeout = timeout

    def _get(self, action: str) -> list[dict]:
        params = {
            "username": self.credentials.username,
            "password": self.credentials.password,
            "action": action,
        }
        url = f"{self.credentials.base_url}/player_api.php?{urlencode(params)}"
        request = Request(url, headers={"User-Agent": "TuTV-Server/1.0"})
        try:
            with urlopen(request, timeout=self.timeout) as response:
                payload = json.loads(response.read().decode("utf-8", errors="replace"))
        except Exception as exc:
            raise XtreamError(f"No se pudo consultar el servidor Xtream: {exc}") from exc
        if not isinstance(payload, list):
            raise XtreamError("El servidor Xtream devolvió una respuesta inesperada")
        return payload

    def build_catalog(self) -> dict:
        live_categories = self._get("get_live_categories")
        vod_categories = self._get("get_vod_categories")
        series_categories = self._get("get_series_categories")
        return {
            "live": {"categories": _categories(live_categories)},
            "movies": {"categories": _categories(vod_categories)},
            "series": {"categories": _categories(series_categories)},
            "generatedBy": "xtream",
        }


def _categories(items: list[dict]) -> list[dict]:
    return [
        {
            "id": str(item.get("category_id", "")),
            "name": str(item.get("category_name", "Sin categoría")),
        }
        for item in items
    ]


def pending_catalog() -> dict:
    return {
        "live": {"categories": []},
        "movies": {"categories": []},
        "series": {"categories": []},
        "generatedBy": "pending-sync",
    }

