"""
VSS API Routes
FastAPI endpoint definitions for Mode 1 queries.

IMPORTANT: This file matches the EXISTING codebase signatures.
- get_llm() is SYNC (not async)
- get_vlm() is SYNC (not async)  
- ClickHouse uses test_connection() method
"""

import logging

from datetime import datetime, timezone
from typing import Optional, Dict

from fastapi import APIRouter, HTTPException

from api.schemas import (
    QueryRequest,
    QueryWithMediaRequest,
    QueryResponse,
    QueryResponseWithTrace,
    HealthResponse,
    HealthComponent,
)
from orchestration.graph import VSSOrchestrator
from storage.clickhouse_client import get_clickhouse
from inference.llm_client import get_llm  # SYNC function
from inference.vlm_client import get_vlm  # SYNC function
from config.settings import get_settings

logger = logging.getLogger(__name__)

router = APIRouter()

# Global orchestrator instance
_orchestrator: Optional[VSSOrchestrator] = None


def get_orchestrator() -> VSSOrchestrator:
    """Get or create orchestrator singleton."""
    global _orchestrator
    if _orchestrator is None:
        _orchestrator = VSSOrchestrator()
    return _orchestrator


# === Query Endpoints ===

@router.post("/query", response_model=QueryResponseWithTrace)
async def query(request: QueryRequest) -> QueryResponseWithTrace:
    """
    Process a natural language query (text only).
    Routes to SQL or VLM based on intent classification.
    """
    logger.info(f"Query received: {request.query[:100]}")
    
    try:
        orchestrator = get_orchestrator()
        state = await orchestrator.run(query=request.query)

        # Only include trace entries in the HTTP response when explicitly requested.
        # The full trace is always persisted to logs/vss_trace.log regardless.
        trace_out = state.get("trace", []) if request.include_trace else []

        return QueryResponseWithTrace(
            request_id=state.get("request_id", "unknown"),
            status="success" if state.get("status") == "completed" else "error",
            response=state.get("final_response", "No response generated"),
            processing_time_ms=state.get("processing_time_ms"),
            trace=trace_out,
            metadata={
                "intent": state.get("intent"),
                "intent_confidence": state.get("intent_confidence"),
                "response_source": state.get("response_source"),
                "escalated": state.get("escalated", False),
                "escalation_reason": state.get("escalation_reason"),
                "sql_query": state.get("sql_query"),
                "routing_reason": state.get("routing_reason"),
            }
        )

    except Exception as exc:
        logger.error("Query failed: %s", exc, exc_info=True)
        raise HTTPException(
            status_code=500,
            detail="An internal error occurred while processing your query. Please try again.",
        )


@router.post("/query/media", response_model=QueryResponseWithTrace)
async def query_with_media(request: QueryWithMediaRequest) -> QueryResponseWithTrace:
    """
    Process a query with image/media upload.
    Always routes to VLM for visual analysis.
    Requires VSS_VLM_ENABLED=true; returns 503 when VLM is disabled.
    """
    settings = get_settings()
    if not settings.vlm_enabled:
        raise HTTPException(
            status_code=503,
            detail="VLM is not enabled. Set VSS_VLM_ENABLED=true to enable media queries.",
        )

    logger.info(f"Media query received: {request.query[:100]}")

    try:
        # Build media dict - use the schema field names from existing code
        media_dict = {
            "type": "image",
            "data": request.media_base64,  # Existing schema uses media_base64
        }
        
        orchestrator = get_orchestrator()
        state = await orchestrator.run(
            query=request.query,
            media=media_dict
        )
        
        return QueryResponseWithTrace(
            request_id=state.get("request_id", "unknown"),
            status="success" if state.get("status") == "completed" else "error",
            response=state.get("final_response", "No response generated"),
            processing_time_ms=state.get("processing_time_ms"),
            trace=state.get("trace", []),
            metadata={
                "intent": state.get("intent"),
                "intent_confidence": state.get("intent_confidence"),
                "response_source": state.get("response_source"),
                "escalated": state.get("escalated", False),
                "media_type": "image",
            }
        )
        
    except Exception as e:
        logger.error("Media query failed: %s", e, exc_info=True)
        raise HTTPException(
            status_code=500,
            detail="An internal error occurred while processing your media query. Please try again.",
        )


# === Health Endpoint ===

@router.get("/health", response_model=HealthResponse)
async def health_check() -> HealthResponse:
    """
    Check service health and component status.
    """
    components: Dict[str, HealthComponent] = {}
    error_count = 0
    
    # Check ClickHouse
    try:
        ch = get_clickhouse()
        ch_ok = ch.test_connection()
        if ch_ok:
            components["clickhouse"] = HealthComponent(status="ok")
        else:
            components["clickhouse"] = HealthComponent(status="error", message="Connection failed")
            error_count += 1
    except Exception as e:
        components["clickhouse"] = HealthComponent(status="error", message=str(e))
        error_count += 1
    
    # Check LLM
    try:
        llm = get_llm()  # Sync function returns client
        llm_ok = await llm.health_check()  # health_check IS async on the client
        if llm_ok:
            components["llm"] = HealthComponent(status="ok")
        else:
            components["llm"] = HealthComponent(status="error", message="Service unavailable")
            error_count += 1
    except Exception as e:
        components["llm"] = HealthComponent(status="error", message=str(e))
        error_count += 1
    
    # Check VLM — only probe when vlm_enabled; otherwise report as disabled
    settings = get_settings()
    if settings.vlm_enabled:
        try:
            vlm = get_vlm()
            vlm_ok = await vlm.health_check()
            if vlm_ok:
                components["vlm"] = HealthComponent(status="ok")
            else:
                components["vlm"] = HealthComponent(status="error", message="Service unavailable")
                error_count += 1
        except Exception as e:
            components["vlm"] = HealthComponent(status="error", message=str(e))
            error_count += 1
    else:
        components["vlm"] = HealthComponent(status="disabled", message="VLM not enabled (VSS_VLM_ENABLED=false)")
    
    # Determine overall status
    if error_count == 0:
        status = "healthy"
    elif error_count < len(components):
        status = "degraded"
    else:
        status = "unhealthy"
    
    return HealthResponse(
        status=status,
        timestamp=datetime.now(timezone.utc),
        components=components,
    )