"""API-backed skill loader for CXCoast platform skills.

Implements BackendProtocol.ls() and download_files() to fetch skills
from the CXCoast API instead of the filesystem. All other BackendProtocol
methods raise NotImplementedError (skills are read-only).
"""
from __future__ import annotations

import logging
from typing import Any

import httpx
from deepagents.backends.protocol import (
    BackendProtocol,
    FileDownloadResponse,
    LsResult,
)

logger = logging.getLogger(__name__)


class ApiBackend(BackendProtocol):
    """Backend that fetches skills from CXCoast API."""

    def __init__(self, api_url: str, api_key: str) -> None:
        self.api_url = api_url
        self.api_key = api_key
        self._skill_list: list[dict[str, Any]] | None = None
        self._content_cache: dict[str, bytes] = {}

    def ls(self, path: str) -> LsResult:
        """Return one 'directory' entry per skill."""
        skills = self._fetch_skills()
        entries = [
            {"path": f"{path}/{s['name']}", "is_dir": True}
            for s in skills
        ]
        return LsResult(entries=entries)

    def download_files(self, paths: list[str]) -> list[FileDownloadResponse]:
        """Download SKILL.md content for each requested path."""
        responses = []
        for path in paths:
            skill = self._resolve_skill(path)
            if skill is None:
                responses.append(FileDownloadResponse(path=path, error="file_not_found"))
                continue
            content = self._fetch_skill_content(skill["id"])
            responses.append(FileDownloadResponse(path=path, content=content))
        return responses

    def _fetch_skills(self) -> list[dict[str, Any]]:
        """Fetch skill list from API (cached per session)."""
        if self._skill_list is not None:
            return self._skill_list
        try:
            headers = {"X-API-Key": self.api_key}
            resp = httpx.get(
                f"{self.api_url}/api/v1/skills/catalog",
                headers=headers, timeout=5.0,
            )
            global_skills = resp.json().get("skills", []) if resp.status_code == 200 else []

            resp2 = httpx.get(
                f"{self.api_url}/api/v1/skills",
                headers=headers, timeout=5.0,
            )
            org_skills = resp2.json().get("skills", []) if resp2.status_code == 200 else []

            by_name: dict[str, dict[str, Any]] = {s["name"]: s for s in global_skills}
            for s in org_skills:
                by_name[s["name"]] = s
            self._skill_list = list(by_name.values())
        except Exception:
            logger.warning("Failed to fetch skills from API", exc_info=True)
            self._skill_list = []
        return self._skill_list

    def _resolve_skill(self, path: str) -> dict[str, Any] | None:
        """Resolve virtual path to skill dict."""
        parts = path.rstrip("/").split("/")
        if len(parts) >= 2 and parts[-1] == "SKILL.md":
            name = parts[-2]
            return next((s for s in self._fetch_skills() if s["name"] == name), None)
        return None

    def _fetch_skill_content(self, skill_id: str) -> bytes:
        """Fetch full skill content by ID."""
        if skill_id in self._content_cache:
            return self._content_cache[skill_id]
        try:
            resp = httpx.get(
                f"{self.api_url}/api/v1/skills/catalog/{skill_id}",
                headers={"X-API-Key": self.api_key},
                timeout=5.0,
            )
            if resp.status_code == 200:
                content = resp.json().get("content", "").encode("utf-8")
                self._content_cache[skill_id] = content
                return content
        except Exception:
            logger.warning("Failed to fetch skill content %s", skill_id, exc_info=True)
        return b""
