"""FastAPI application for the specialist inference service."""

from __future__ import annotations

import logging
import os
import time
from contextlib import asynccontextmanager

from fastapi import FastAPI

from services.specialist.engine import SpecialistEngine
from services.specialist.router import router, set_engine

logger = logging.getLogger(__name__)

# ---------------------------------------------------------------------------
# Configuration
# ---------------------------------------------------------------------------

SPECIALIST_MODEL = os.environ.get("SPECIALIST_MODEL", "urchade/gliner_large-v2.1")
MAX_BATCH_SIZE = int(os.environ.get("SPECIALIST_MAX_BATCH_SIZE", "32"))
MAX_WAIT_MS = float(os.environ.get("SPECIALIST_MAX_WAIT_MS", "50.0"))
MAX_QUEUE_SIZE = int(os.environ.get("SPECIALIST_MAX_QUEUE_SIZE", "256"))


# ---------------------------------------------------------------------------
# Lifespan: load model and warm up on startup
# ---------------------------------------------------------------------------


@asynccontextmanager
async def lifespan(app: FastAPI):
    """Application lifespan — loads model and warms up on startup."""
    engine = SpecialistEngine(
        model_name=SPECIALIST_MODEL,
        max_batch_size=MAX_BATCH_SIZE,
        max_wait_ms=MAX_WAIT_MS,
        max_queue_size=MAX_QUEUE_SIZE,
    )
    engine.load_model()
    engine.warm_up()
    app.state.engine = engine
    set_engine(engine)
    logger.info(
        "Specialist service ready: model=%s, max_batch=%d, max_wait_ms=%.1f, max_queue=%d",
        SPECIALIST_MODEL,
        MAX_BATCH_SIZE,
        MAX_WAIT_MS,
        MAX_QUEUE_SIZE,
    )
    yield
    logger.info("Specialist service shutting down")


# ---------------------------------------------------------------------------
# App
# ---------------------------------------------------------------------------

app = FastAPI(
    title="Specialist Inference Service",
    description="CPU-first NER, classification, relation, and structured extraction",
    version="1.0.0",
    lifespan=lifespan,
)

app.include_router(router)

# Track startup time for metrics
_start_time = time.time()


# ---------------------------------------------------------------------------
# Health / Readiness endpoints
# ---------------------------------------------------------------------------


@app.get("/health")
async def health():
    """Liveness probe — returns 200 if the process is running."""
    return {"status": "ok"}


@app.get("/ready")
async def ready():
    """Readiness probe — returns 200 only when the engine is loaded."""
    engine = getattr(app.state, "engine", None)
    if engine is None or not engine.is_ready:
        return {"status": "not_ready"}, 503
    return {
        "status": "ready",
        "model": engine.model_name,
        "uptime_seconds": round(time.time() - _start_time, 1),
    }


@app.get("/metrics")
async def metrics():
    """Basic Prometheus-style metrics endpoint."""
    engine = getattr(app.state, "engine", None)
    model_loaded = 1 if (engine and engine.is_ready) else 0
    uptime = round(time.time() - _start_time, 1)

    batcher_metrics = engine.batcher_metrics if engine else {}

    return {
        "specialist_model_loaded": model_loaded,
        "specialist_uptime_seconds": uptime,
        "specialist_max_batch_size": MAX_BATCH_SIZE,
        "specialist_max_wait_ms": MAX_WAIT_MS,
        "specialist_max_queue_size": MAX_QUEUE_SIZE,
        "specialist_model_name": SPECIALIST_MODEL,
        "specialist_total_batches": batcher_metrics.get("total_batches", 0),
        "specialist_total_items": batcher_metrics.get("total_items", 0),
        "specialist_total_rejections": batcher_metrics.get("total_rejections", 0),
        "specialist_queue_depth": batcher_metrics.get("queue_depth", 0),
    }
