"""
Health Check Endpoints
======================
K8s probes + Real component health checks

Endpoints:
- GET /health         - Full health check with component probes
- GET /health/ready   - K8s readinessProbe
- GET /health/live    - K8s livenessProbe

Components Checked:
- PostgreSQL (192.168.0.188:5432)
- Redis (192.168.0.188:6380)
- Ollama (192.168.0.188:11434)
- OpenClaw (192.168.0.188:8089)
- SigNoz (192.168.0.188:3301)
"""

import asyncio
from datetime import UTC, datetime
from typing import Literal

from fastapi import APIRouter
from pydantic import BaseModel

from src.core.config import settings
from src.core.logging import get_logger
from src.services.health_check_service import get_health_check_service

router = APIRouter()
logger = get_logger("awoooi.health")


# =============================================================================
# Response Models
# =============================================================================

class ComponentHealth(BaseModel):
    """Individual component health status"""
    status: Literal["up", "down", "degraded"]
    latency_ms: float | None = None
    error: str | None = None


class HealthResponse(BaseModel):
    """Full health check response"""
    status: Literal["healthy", "degraded", "unhealthy"]
    version: str
    environment: str
    mock_mode: bool
    timestamp: datetime
    components: dict[str, ComponentHealth]


# =============================================================================
# Health Check Functions (Async-First)
# =============================================================================

async def _http_health_check(
    name: str,
    url: str,
    path: str = "/health",
) -> ComponentHealth:
    """
    Generic async HTTP health check

    Phase 22 P0 修復: 使用 HealthCheckService (2026-03-31)
    """
    service = get_health_check_service()
    result = await service.http_health_check(name=name, url=url, path=path)
    return ComponentHealth(
        status=result.status,
        latency_ms=result.latency_ms,
        error=result.error,
    )


async def check_postgresql() -> ComponentHealth:
    """
    Async PostgreSQL health check via TCP connect

    Phase 22 P0 修復: 使用 HealthCheckService (2026-03-31)
    """
    service = get_health_check_service()
    result = await service.postgresql_tcp_check()
    return ComponentHealth(
        status=result.status,
        latency_ms=result.latency_ms,
        error=result.error,
    )


async def check_redis() -> ComponentHealth:
    """
    Async Redis health check via PING

    Phase 22 P0 修復: 使用 HealthCheckService (2026-03-31)
    """
    service = get_health_check_service()
    result = await service.redis_ping_check()
    return ComponentHealth(
        status=result.status,
        latency_ms=result.latency_ms,
        error=result.error,
    )


async def check_ollama() -> ComponentHealth:
    """Async Ollama health check via /api/tags"""
    return await _http_health_check("ollama", settings.OLLAMA_URL, "/api/tags")


async def check_openclaw() -> ComponentHealth:
    """Async OpenClaw health check via /health"""
    return await _http_health_check("openclaw", settings.OPENCLAW_URL, "/health")


async def check_signoz() -> ComponentHealth:
    """Async SigNoz health check"""
    return await _http_health_check("signoz", settings.SIGNOZ_URL, "/api/v1/health")


# =============================================================================
# Endpoints
# =============================================================================

@router.get("/health", response_model=HealthResponse)
async def get_health() -> HealthResponse:
    """
    Full health check with real component probes

    Performs async health checks on all external dependencies:
    - PostgreSQL: Primary database
    - Redis: Cache layer
    - Ollama: Local LLM service
    - OpenClaw: AI Agent service
    - SigNoz: Observability platform

    Returns overall system status based on component health.
    """
    # Run all health checks concurrently (Async-First)
    results = await asyncio.gather(
        check_postgresql(),
        check_redis(),
        check_ollama(),
        check_openclaw(),
        check_signoz(),
    )

    components = {
        "api": ComponentHealth(status="up", latency_ms=0.0),
        "postgresql": results[0],
        "redis": results[1],
        "ollama": results[2],
        "openclaw": results[3],
        "signoz": results[4],
    }

    # Determine overall status
    statuses = [c.status for c in components.values()]
    down_count = statuses.count("down")
    degraded_count = statuses.count("degraded")

    # Critical services: postgresql, redis
    critical_down = components["postgresql"].status == "down" or components["redis"].status == "down"

    if critical_down or down_count >= 3:
        overall_status: Literal["healthy", "degraded", "unhealthy"] = "unhealthy"
    elif down_count >= 1 or degraded_count > 0:
        overall_status = "degraded"
    else:
        overall_status = "healthy"

    logger.info(
        "health_check_complete",
        status=overall_status,
        mock_mode=settings.MOCK_MODE,
        components={k: v.status for k, v in components.items()},
    )

    return HealthResponse(
        status=overall_status,
        version=settings.VERSION,
        environment=settings.ENVIRONMENT,
        mock_mode=settings.MOCK_MODE,
        timestamp=datetime.now(UTC),
        components=components,
    )


@router.get("/health/ready")
async def get_readiness() -> dict[str, str]:
    """
    K8s readinessProbe

    Returns 200 when the service is ready to accept traffic.
    Lightweight check - doesn't probe external services.
    """
    logger.debug("readiness_probe")
    return {"status": "ready"}


@router.get("/health/live")
async def get_liveness() -> dict[str, str]:
    """
    K8s livenessProbe

    Returns 200 when the service is alive.
    Used by K8s to determine if pod needs restart.
    """
    logger.debug("liveness_probe")
    return {"status": "alive"}


@router.get("/health/ai-usage")
async def get_ai_usage() -> dict:
    """
    AI API 用量監控

    Phase 13.2: Rate Limiter 整合 (2026-03-26)
    監控 Gemini/Claude API 使用量，防止暴衝。

    Returns:
        dict: 各 provider 用量統計
    """
    from src.services.ai_rate_limiter import get_ai_rate_limiter

    rate_limiter = get_ai_rate_limiter()

    gemini_stats = await rate_limiter.get_usage_stats("gemini")
    claude_stats = await rate_limiter.get_usage_stats("claude")

    return {
        "gemini": gemini_stats,
        "claude": claude_stats,
        "fallback_order": settings.AI_FALLBACK_ORDER,
    }
