"""ALP HTTP server for skill exchange.

Lightweight HTTP server using Python's built-in http.server module.
Runs in a daemon thread so the main process stays interactive.

Endpoints:
    GET /alp/card      — Returns this agent's AgentCard as JSON.
    GET /alp/skills    — Returns skill catalog (no code).
    GET /alp/skill/<n> — Returns full skill package with code and metadata.
"""

from __future__ import annotations

import json
import threading
from http.server import BaseHTTPRequestHandler, HTTPServer
from pathlib import Path
from typing import Any

from alive.network.conversation_log import log_event

DEFAULT_PORT = 8484


class ALPHandler(BaseHTTPRequestHandler):
    """HTTP request handler for ALP endpoints."""

    def do_GET(self) -> None:  # noqa: N802
        """Handle GET requests."""
        path = self.path.rstrip("/")

        if path == "/alp/card":
            self._handle_card()
        elif path == "/alp/skills":
            self._handle_skills()
        elif path.startswith("/alp/skill/"):
            skill_name = path[len("/alp/skill/") :]
            self._handle_skill(skill_name)
        else:
            self._send_json({"error": "Not found"}, 404)

    def _handle_card(self) -> None:
        from alive.network.identity import get_agent_card

        card = get_agent_card()
        peer_ip = self.client_address[0]
        log_event("CARD_REQUEST", f"Agent card requested by {peer_ip}")
        self._send_json(card)

    def _handle_skills(self) -> None:
        from alive.core.skill_registry import get_registry

        registry = get_registry()
        skills = registry.list_skills_only()
        catalog = []
        for s in skills:
            meta_path = registry._skills_dir / s.name / "metadata.json"
            generation = 1
            times_used = s.times_used
            if meta_path.exists():
                try:
                    meta = json.loads(meta_path.read_text())
                    generation = meta.get("generation", 1)
                except (json.JSONDecodeError, OSError):
                    pass
            catalog.append(
                {
                    "name": s.name,
                    "description": s.description,
                    "confidence": s.confidence_score,
                    "generation": generation,
                    "times_used": times_used,
                }
            )
        peer_ip = self.client_address[0]
        log_event("BROWSE", f"{peer_ip} requested our skill catalog")
        self._send_json(catalog)

    def _handle_skill(self, skill_name: str) -> None:
        from alive.core.skill_registry import get_registry

        registry = get_registry()
        try:
            info = registry.get_skill(skill_name)
        except KeyError:
            self._send_json({"error": f"Skill '{skill_name}' not found"}, 404)
            return

        skill_dir: Path = registry._skills_dir / skill_name

        code = _read_file(skill_dir / "skill.py")
        test_code = _read_file(skill_dir / "test_skill.py")
        description = _read_file(skill_dir / "SKILL.md")
        birth_story = _read_json(skill_dir / "birth_story.json")
        metadata = _read_json(skill_dir / "metadata.json") or {}

        generation = metadata.get("generation", 1)
        lineage = metadata.get("lineage", [])

        package: dict[str, Any] = {
            "name": skill_name,
            "code": code,
            "test_code": test_code,
            "metadata": metadata,
            "birth_story": birth_story,
            "description": description or "",
            "generation": generation,
            "lineage": lineage,
        }
        peer_ip = self.client_address[0]
        log_event(
            "SKILL_REQUEST",
            f"{peer_ip} wants '{skill_name}'",
        )
        log_event("SENT", f"{skill_name} to {peer_ip} (gen {generation})")
        self._send_json(package)

    def _send_json(self, data: Any, status: int = 200) -> None:
        body = json.dumps(data, default=str).encode("utf-8")
        self.send_response(status)
        self.send_header("Content-Type", "application/json")
        self.send_header("Content-Length", str(len(body)))
        self.end_headers()
        self.wfile.write(body)

    def log_message(self, format: str, *args: Any) -> None:  # noqa: A002
        """Suppress default stderr logging."""
        pass


def _read_file(path: Path) -> str | None:
    """Read a text file or return None if it doesn't exist."""
    if path.exists():
        try:
            return path.read_text()
        except OSError:
            return None
    return None


def _read_json(path: Path) -> dict[str, Any] | None:
    """Read a JSON file or return None if it doesn't exist."""
    if path.exists():
        try:
            return json.loads(path.read_text())
        except (json.JSONDecodeError, OSError):
            return None
    return None


def start_server(port: int = DEFAULT_PORT) -> tuple[HTTPServer, threading.Thread]:
    """Start the ALP HTTP server in a daemon thread.

    Args:
        port: Port to listen on (default 8484).

    Returns:
        Tuple of (server_instance, server_thread).
    """
    server = HTTPServer(("0.0.0.0", port), ALPHandler)
    server.timeout = 1.0

    thread = threading.Thread(
        target=server.serve_forever,
        daemon=True,
        name="alp-http-server",
    )
    thread.start()
    log_event("SERVER", f"HTTP server started on port {port}")
    return server, thread
