"""
Minimal HTTP API — lightweight asyncio server (no framework dependency).

Endpoints:
    GET /health         → service health
    GET /metrics        → Prometheus metrics
    GET /state/latest   → latest trade/quote per symbol (?symbol=BTCUSDT)
    GET /features/latest → latest computed features (?symbol=BTCUSDT)
    GET /stats          → queue fill, drops, events/sec
"""
from __future__ import annotations

import asyncio
import json
import logging

from prometheus_client import CONTENT_TYPE_LATEST, generate_latest

from senpai.md_consumer.config import settings
from senpai.md_consumer.features import compute_features
from senpai.md_consumer.state import LatestState

logger = logging.getLogger(__name__)

# These are set by main.py at startup
_state: LatestState | None = None
_stats_fn = None  # callable → dict
_features_cache: dict[str, dict] = {}  # symbol → last computed features


def set_state(state: LatestState) -> None:
    global _state
    _state = state


def set_stats_fn(fn) -> None:
    global _stats_fn
    _stats_fn = fn


def cache_features(symbol: str, features: dict) -> None:
    """Cache pre-computed features for fast API responses."""
    _features_cache[symbol] = features


async def _handler(reader: asyncio.StreamReader, writer: asyncio.StreamWriter):
    """Minimal HTTP request handler."""
    try:
        request_line = await asyncio.wait_for(reader.readline(), timeout=5.0)
        request_str = request_line.decode("utf-8", errors="replace").strip()

        parts = request_str.split()
        if len(parts) < 2:
            writer.close()
            return
        path = parts[1]

        # Consume headers
        while True:
            line = await reader.readline()
            if line in (b"\r\n", b"\n", b""):
                break

        # Parse query params
        query_params: dict[str, str] = {}
        if "?" in path:
            base_path, query = path.split("?", 1)
            for param in query.split("&"):
                if "=" in param:
                    k, v = param.split("=", 1)
                    query_params[k] = v
        else:
            base_path = path

        body, content_type, status = await _route(base_path, query_params)

        response = (
            f"HTTP/1.1 {status}\r\n"
            f"Content-Type: {content_type}\r\n"
            f"Content-Length: {len(body)}\r\n"
            f"Connection: close\r\n"
            f"\r\n"
        )
        writer.write(response.encode() + body)
        await writer.drain()
    except Exception:
        pass
    finally:
        try:
            writer.close()
            await writer.wait_closed()
        except Exception:
            pass


async def _route(
    path: str, params: dict[str, str]
) -> tuple[bytes, str, str]:
    """Route request to handler. Returns (body, content_type, status)."""

    if path == "/health":
        body = json.dumps({
            "status": "ok",
            "service": "senpai-md-consumer",
            "symbols": _state.symbols if _state else [],
        }).encode()
        return body, "application/json", "200 OK"

    elif path == "/metrics":
        body = generate_latest()
        return body, CONTENT_TYPE_LATEST, "200 OK"

    elif path == "/state/latest":
        symbol = params.get("symbol", "")
        if not symbol:
            body = json.dumps({"error": "missing ?symbol=XXX"}).encode()
            return body, "application/json", "400 Bad Request"
        if not _state:
            body = json.dumps({"error": "not initialized"}).encode()
            return body, "application/json", "503 Service Unavailable"
        data = _state.to_dict(symbol)
        body = json.dumps(data, ensure_ascii=False).encode()
        return body, "application/json", "200 OK"

    elif path == "/features/latest":
        symbol = params.get("symbol", "").upper()
        if not symbol:
            body = json.dumps({"error": "missing ?symbol=XXX"}).encode()
            return body, "application/json", "400 Bad Request"
        cached = _features_cache.get(symbol)
        if cached:
            data = {"symbol": symbol, "features": cached}
        elif _state:
            # Fallback to live compute (slower)
            data = {"symbol": symbol, "features": compute_features(_state, symbol)}
        else:
            body = json.dumps({"error": "not initialized"}).encode()
            return body, "application/json", "503 Service Unavailable"
        body = json.dumps(data, ensure_ascii=False).encode()
        return body, "application/json", "200 OK"

    elif path == "/stats":
        if _stats_fn:
            data = _stats_fn()
        else:
            data = {"error": "not initialized"}
        body = json.dumps(data, ensure_ascii=False).encode()
        return body, "application/json", "200 OK"

    else:
        body = json.dumps({"error": "not found"}).encode()
        return body, "application/json", "404 Not Found"


async def start_api() -> asyncio.Server:
    """Start the HTTP server."""
    server = await asyncio.start_server(
        _handler,
        settings.http_host,
        settings.http_port,
    )
    logger.info(
        "api.started",
        extra={
            "host": settings.http_host,
            "port": settings.http_port,
            "endpoints": [
                "/health",
                "/metrics",
                "/state/latest?symbol=",
                "/features/latest?symbol=",
                "/stats",
            ],
        },
    )
    return server
