"""FastAPI Application Entry Point for the Xulcan ProtoKernel."""

import logging.config
import os
from contextlib import asynccontextmanager
from typing import AsyncGenerator

from fastapi import FastAPI, HTTPException, Request, status
from fastapi.responses import JSONResponse
from pydantic import BaseModel

from xulcan.api.middleware import RequestCorrelationMiddleware
from xulcan.config import get_settings
from xulcan.logging_config import (
    configure_structlog_wrapper,
    get_logger,
    get_logging_config,
)

# 🛡️ IMPORTAMOS TU CLIENTE MAESTRO
from xulcan.app import XulcanClient

# ═══════════════════════════════════════════════════════════════════════════
# COMPOSITION ROOT (Ahora delegado al Client)
# ═══════════════════════════════════════════════════════════════════════════

@asynccontextmanager
async def lifespan(app: FastAPI) -> AsyncGenerator[None, None]:
    settings = get_settings()
    
    logging_config = get_logging_config(settings)
    logging.config.dictConfig(logging_config)
    configure_structlog_wrapper(settings)
    logger = get_logger("lifespan")
    
    logger.info("🚀 Booting Xulcan Agent OS Server...", extra={"env": settings.ENVIRONMENT})

    try:
        # 1. Obtenemos las llaves de la configuración segura de Pydantic
        gemini_key = settings.GEMINI_API_KEY.get_secret_value() if settings.GEMINI_API_KEY else None
        
        # 2. ⚡ LA MAGIA: Instanciamos tu cliente (que ya tiene el Sandbox, la Red y los LLMs listos)
        client = XulcanClient(gemini_api_key=gemini_key)
        
        # 3. Lo inyectamos en el estado global de la app
        app.state.client = client
        app.state.is_ready = True
        logger.info("✅ Xulcan Client successfully wrapped in FastAPI.")
        
    except Exception as e:
        logger.critical("🔥 Kernel Panic during server startup", exc_info=True)
        app.state.is_ready = False
        raise e

    yield

    logger.info("🛑 Xulcan Shutdown: Flushing memory and closing connections.")
    app.state.is_ready = False


# ═══════════════════════════════════════════════════════════════════════════
# FASTAPI INSTANCE & DTOs
# ═══════════════════════════════════════════════════════════════════════════

app = FastAPI(
    title=os.getenv("PROJECT_NAME", "Xulcan Agent OS"),
    version="0.3.0-beta",
    lifespan=lifespan,
)

app.add_middleware(RequestCorrelationMiddleware)

class RunRequest(BaseModel):
    input_text: str

class RunResponse(BaseModel):
    run_id: str
    output: str  # Cambiado a str para coincidir con tu client.run()


# ═══════════════════════════════════════════════════════════════════════════
# AGENT ENDPOINTS
# ═══════════════════════════════════════════════════════════════════════════

@app.post("/v1/agent/run", response_model=RunResponse)
async def run_agent(request: Request, body: RunRequest):
    """Execute the agent given a user input."""
    client: XulcanClient = request.app.state.client
    
    try:
        # Usamos tu cliente tal cual lo usaste en demo.py
        run_id, response_text = await client.run(body.input_text)
        
        return RunResponse(
            run_id=run_id,
            output=response_text
        )
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))

@app.get("/v1/runs/{run_id}/audit")
async def get_run_audit(request: Request, run_id: str):
    """Fetch the immutable history and current summary of a run."""
    client: XulcanClient = request.app.state.client
    
    result = await client.get_audit(run_id)
    if "error" in result:
        raise HTTPException(status_code=404, detail=result["error"])
        
    return result


# ═══════════════════════════════════════════════════════════════════════════
# SYSTEM ENDPOINTS (Kubernetes & Error Handling)
# ═══════════════════════════════════════════════════════════════════════════

@app.exception_handler(Exception)
async def global_exception_handler(request: Request, exc: Exception):
    logger = get_logger("exception_handler")
    logger.error("Unhandled exception trapped at API edge", error=str(exc), path=request.url.path, exc_info=True)
    return JSONResponse(status_code=500, content={"detail": "Internal Kernel Error"})

@app.get("/health/live", status_code=200, tags=["System"])
async def liveness_probe() -> dict[str, str]:
    return {"status": "alive"}

@app.get("/health/ready", status_code=200, tags=["System"])
async def readiness_probe(request: Request) -> dict[str, str]:
    if not getattr(request.app.state, "is_ready", False):
        raise HTTPException(status_code=503, detail="Kernel infrastructure is initializing or panicked")
    return {"status": "ready"}