"""HTTP API server for Agent Johnny 5 daemon.

Lightweight REST API on localhost:8585 using stdlib ThreadingHTTPServer.
No external web framework needed. Access remotely via SSH tunnel:
    ssh -L 8585:localhost:8585 root@YOUR_VPS

Endpoints:
    POST /chat    — Send message to agent (requires LLM)
    GET  /status  — OpenClaw service status (no LLM)
    POST /restart — Restart OpenClaw gateway (no LLM)
    GET  /health  — Health check results (no LLM)
    GET  /logs    — Recent gateway logs (no LLM)

All endpoints require: Authorization: Bearer <token>
"""

from __future__ import annotations

import json
import logging
import subprocess
import threading
from http.server import BaseHTTPRequestHandler, ThreadingHTTPServer
from typing import TYPE_CHECKING

if TYPE_CHECKING:
    from ..agent.brain import AgentBrain
    from .health_monitor import HealthMonitor

from ..agent.output import OutputHandler

logger = logging.getLogger(__name__)

DEFAULT_PORT = 8585
SERVICE_NAME = "openclaw-gateway"


class CollectorOutputHandler:
    """OutputHandler that collects agent responses into a buffer."""

    def __init__(self) -> None:
        self._replies: list[str] = []

    def on_typing(self) -> None:
        pass

    def on_reply(self, text: str) -> None:
        self._replies.append(text)

    def on_tool_call(self, tool_name: str, args: dict) -> None:
        pass

    def on_error(self, error: str) -> None:
        self._replies.append(f"[Error: {error}]")

    def get_response(self) -> str:
        return "\n".join(self._replies)


class _APIHandler(BaseHTTPRequestHandler):
    """HTTP request handler for the daemon API."""

    # Set by HTTPAPIServer before starting
    agent: AgentBrain = None  # type: ignore
    monitor: HealthMonitor = None  # type: ignore
    api_token: str = ""

    def log_message(self, format: str, *args) -> None:
        logger.info("HTTP API: " + format, *args)

    def _check_auth(self) -> bool:
        auth = self.headers.get("Authorization", "")
        if auth != f"Bearer {self.api_token}":
            self._json_response(401, {"error": "Unauthorized"})
            return False
        return True

    def _json_response(self, status: int, data: dict) -> None:
        body = json.dumps(data).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 _read_body(self) -> dict:
        length = int(self.headers.get("Content-Length", 0))
        if length == 0:
            return {}
        raw = self.rfile.read(length)
        try:
            return json.loads(raw)
        except json.JSONDecodeError:
            return {}

    # ------------------------------------------------------------------
    # Routes
    # ------------------------------------------------------------------

    def do_GET(self) -> None:
        if not self._check_auth():
            return

        if self.path == "/status":
            self._handle_status()
        elif self.path == "/health":
            self._handle_health()
        elif self.path == "/logs":
            self._handle_logs()
        else:
            self._json_response(404, {"error": "Not found"})

    def do_POST(self) -> None:
        if not self._check_auth():
            return

        if self.path == "/chat":
            self._handle_chat()
        elif self.path == "/restart":
            self._handle_restart()
        else:
            self._json_response(404, {"error": "Not found"})

    # ------------------------------------------------------------------
    # Handlers (no LLM except /chat)
    # ------------------------------------------------------------------

    def _handle_status(self) -> None:
        """Service status via subprocess."""
        try:
            result = subprocess.run(
                ["systemctl", "is-active", SERVICE_NAME],
                capture_output=True, text=True, timeout=10,
            )
            active = result.stdout.strip() == "active"
            self._json_response(200, {
                "service": SERVICE_NAME,
                "active": active,
                "status": result.stdout.strip(),
            })
        except Exception as exc:
            self._json_response(500, {"error": str(exc)})

    def _handle_health(self) -> None:
        """Health check results from monitor."""
        if self.monitor:
            self._json_response(200, self.monitor.get_status())
        else:
            self._json_response(200, {"error": "Health monitor not running"})

    def _handle_logs(self) -> None:
        """Recent gateway journal logs."""
        try:
            result = subprocess.run(
                ["journalctl", "-u", SERVICE_NAME, "-n", "50", "--no-pager"],
                capture_output=True, text=True, timeout=10,
            )
            self._json_response(200, {
                "logs": result.stdout,
                "lines": 50,
            })
        except Exception as exc:
            self._json_response(500, {"error": str(exc)})

    def _handle_restart(self) -> None:
        """Restart the OpenClaw gateway."""
        try:
            subprocess.run(
                ["systemctl", "restart", SERVICE_NAME],
                capture_output=True, text=True, timeout=30,
            )
            import time
            time.sleep(8)

            result = subprocess.run(
                ["systemctl", "is-active", SERVICE_NAME],
                capture_output=True, text=True, timeout=10,
            )
            active = result.stdout.strip() == "active"
            self._json_response(200, {
                "restarted": True,
                "active": active,
                "status": result.stdout.strip(),
            })
        except Exception as exc:
            self._json_response(500, {"error": str(exc)})

    def _handle_chat(self) -> None:
        """Send message to agent (uses LLM)."""
        body = self._read_body()
        message = body.get("message", "").strip()

        if not message:
            self._json_response(400, {"error": "Missing 'message' field"})
            return

        if not self.agent:
            self._json_response(500, {"error": "Agent not initialized"})
            return

        collector = CollectorOutputHandler()
        try:
            self.agent.handle_user_message(message, collector)
            self._json_response(200, {
                "response": collector.get_response(),
            })
        except Exception as exc:
            logger.exception("Chat handler error")
            self._json_response(500, {"error": str(exc)})


class HTTPAPIServer:
    """Manages the HTTP API server in a background thread."""

    def __init__(
        self,
        agent: AgentBrain,
        monitor: HealthMonitor,
        api_token: str,
        port: int = DEFAULT_PORT,
    ) -> None:
        self._agent = agent
        self._monitor = monitor
        self._api_token = api_token
        self._port = port
        self._server: ThreadingHTTPServer | None = None
        self._thread: threading.Thread | None = None

    def start(self) -> None:
        """Start the HTTP API server in a background thread."""
        # Configure handler class with shared state
        _APIHandler.agent = self._agent
        _APIHandler.monitor = self._monitor
        _APIHandler.api_token = self._api_token

        self._server = ThreadingHTTPServer(
            ("127.0.0.1", self._port), _APIHandler
        )
        self._thread = threading.Thread(
            target=self._server.serve_forever,
            name="easyclaw-http-api",
            daemon=True,
        )
        self._thread.start()
        logger.info("HTTP API server started on 127.0.0.1:%d", self._port)

    def stop(self) -> None:
        """Shut down the HTTP API server."""
        if self._server:
            self._server.shutdown()
        logger.info("HTTP API server stopped")
