"""Node Worker — NATS offload executor for cross-node inference."""
import logging
import os

from fastapi import FastAPI

import config
import worker

logging.basicConfig(level=logging.INFO)
logger = logging.getLogger("node-worker")

app = FastAPI(title="Node Worker", version="1.0.0")

_nats_client = None


@app.get("/healthz")
async def healthz():
    connected = _nats_client is not None and _nats_client.is_connected if _nats_client else False
    return {
        "status": "ok" if connected else "degraded",
        "node_id": config.NODE_ID,
        "nats_connected": connected,
        "max_concurrency": config.MAX_CONCURRENCY,
    }


@app.get("/metrics")
async def metrics():
    return worker.get_metrics()


@app.get("/prom_metrics")
async def prom_metrics():
    from fastapi.responses import Response
    import fabric_metrics as fm
    data = fm.get_metrics_text()
    if data:
        return Response(content=data, media_type="text/plain; charset=utf-8")
    return {"error": "prometheus_client not installed"}


@app.get("/caps")
async def caps():
    """Capability flags for NCS to aggregate.

    Semantic vs operational separation (contract):
    - capabilities.voice_* = semantic availability (provider configured).
      True as long as the provider is configured, regardless of NATS state.
      Routing decisions are based on this.
    - runtime.nats_subscriptions.voice_* = operational (NATS sub active).
      Used for health/telemetry only — NOT for routing.

    This prevents false-negatives during reconnects / restart races.
    """
    import worker as _w
    nid = config.NODE_ID.lower()

    # Semantic: provider configured → capability is available
    voice_tts_cap = config.TTS_PROVIDER != "none"
    voice_stt_cap = config.STT_PROVIDER != "none"
    voice_llm_cap = True  # LLM always available when node-worker is up

    # Operational: actual NATS subscription state (health/telemetry only)
    nats_voice_tts_active = f"node.{nid}.voice.tts.request" in _w._VOICE_SUBJECTS
    nats_voice_stt_active = f"node.{nid}.voice.stt.request" in _w._VOICE_SUBJECTS
    nats_voice_llm_active = f"node.{nid}.voice.llm.request" in _w._VOICE_SUBJECTS

    return {
        "node_id": config.NODE_ID,
        "capabilities": {
            "llm": True,
            "vision": True,
            "stt": config.STT_PROVIDER != "none",
            "tts": config.TTS_PROVIDER != "none",
            "ocr": config.OCR_PROVIDER != "none",
            "image": config.IMAGE_PROVIDER != "none",
            # Voice HA semantic capability flags (provider-based, not NATS-based)
            "voice_tts": voice_tts_cap,
            "voice_llm": voice_llm_cap,
            "voice_stt": voice_stt_cap,
        },
        "providers": {
            "stt": config.STT_PROVIDER,
            "tts": config.TTS_PROVIDER,
            "ocr": config.OCR_PROVIDER,
            "image": config.IMAGE_PROVIDER,
        },
        "defaults": {
            "llm": config.DEFAULT_LLM,
            "vision": config.DEFAULT_VISION,
        },
        "concurrency": config.MAX_CONCURRENCY,
        "voice_concurrency": {
            "voice_tts": config.VOICE_MAX_CONCURRENT_TTS,
            "voice_llm": config.VOICE_MAX_CONCURRENT_LLM,
            "voice_stt": config.VOICE_MAX_CONCURRENT_STT,
        },
        # Operational NATS subscription state — for health/monitoring only
        "runtime": {
            "nats_subscriptions": {
                "voice_tts_active": nats_voice_tts_active,
                "voice_stt_active": nats_voice_stt_active,
                "voice_llm_active": nats_voice_llm_active,
            }
        },
    }


@app.on_event("startup")
async def startup():
    global _nats_client
    try:
        import nats as nats_lib
        _nats_client = await nats_lib.connect(config.NATS_URL)
        logger.info(f"✅ NATS connected: {config.NATS_URL}")
        await worker.start(_nats_client)
        logger.info(f"✅ Node Worker ready: node={config.NODE_ID} concurrency={config.MAX_CONCURRENCY}")
    except Exception as e:
        logger.error(f"❌ Startup failed: {e}")


@app.on_event("shutdown")
async def shutdown():
    if _nats_client:
        try:
            await _nats_client.close()
        except Exception:
            pass


if __name__ == "__main__":
    import uvicorn
    uvicorn.run(app, host="0.0.0.0", port=config.PORT)
