"""
API Health Check Endpoints for FoundryMatch SaaS
================================================
Provides endpoints for monitoring the health and status of critical
application components like the database, Redis, and background collectors.
"""

from __future__ import annotations
from datetime import datetime, timezone
import logging
import os
import time
from typing import Dict, Any

import redis.asyncio as aioredis
from fastapi import APIRouter, Request
from sqlalchemy import text

from .. import settings as saas_settings
from ..db import AsyncSessionLocal

router = APIRouter(prefix="/api/v1", tags=["monitoring"])
log = logging.getLogger(__name__)

ERROR_CODES = {
    "connection_failed": "Connection failed",
    "timeout": "Connection timeout",
    "auth_failed": "Authentication failed",
    "unknown": "Health check failed",
}


def _sanitize_error(e: Exception) -> str:
    error_str = str(e).lower()
    if "timeout" in error_str:
        return ERROR_CODES["timeout"]
    if "auth" in error_str or "permission" in error_str:
        return ERROR_CODES["auth_failed"]
    if "connection" in error_str or "refused" in error_str:
        return ERROR_CODES["connection_failed"]
    return ERROR_CODES["unknown"]


def _normalize_circuit_state(state: str) -> str:
    state_lower = state.lower()
    if "half" in state_lower:
        return "half-open"
    if "open" in state_lower:
        return "open"
    if "closed" in state_lower:
        return "closed"
    return "unknown"


def _get_circuit_state(service: str) -> str:
    try:
        if service == "stripe":
            from ..billing import metering as billing_metering

            breaker = getattr(
                billing_metering,
                "stripe_breaker",
                getattr(billing_metering, "billing_circuit_breaker", None),
            )
            if breaker is None:
                return "unknown"
            state = getattr(breaker, "current_state", None)
            if state is None:
                return "unknown"
            state_name = getattr(state, "name", None) or str(state)
            return _normalize_circuit_state(state_name)
        return "unknown"
    except Exception:
        return "unknown"


@router.get("/health", tags=["monitoring"])
async def health_basic() -> Dict[str, str]:
    """
    Basic health check to confirm the API is running.
    """
    return {"status": "ok"}


@router.get("/health/full", tags=["monitoring"])
async def health_full(request: Request) -> Dict[str, Any]:
    """
    Comprehensive health check for monitoring all critical systems.
    This endpoint checks the database, Redis, and background collectors.
    """
    health_status: Dict[str, Any] = {
        "status": "healthy",
        "timestamp": datetime.utcnow().isoformat(),
        "checks": {},
    }

    # Check Database connection (assumes 'async_engine' is on app.state)
    if hasattr(request.app.state, "async_engine"):
        try:
            async with request.app.state.async_engine.connect() as conn:
                await conn.execute(text("SELECT 1"))
            health_status["checks"]["database"] = "ok"
        except Exception as e:
            health_status["checks"]["database"] = f"error: {str(e)}"
            health_status["status"] = "unhealthy"
    else:
        health_status["checks"]["database"] = "not configured"
        health_status["status"] = "degraded"

    # Check Redis connection (assumes 'redis_conn' is on app.state)
    if hasattr(request.app.state, "redis_conn"):
        try:
            await request.app.state.redis_conn.ping()
            health_status["checks"]["redis"] = "ok"
        except Exception as e:
            health_status["checks"]["redis"] = f"error: {str(e)}"
            health_status["status"] = "unhealthy"
    else:
        health_status["checks"]["redis"] = "not configured"
        health_status["status"] = "degraded"

    # Check Collectors (assumes they are on app.state)
    health_status["checks"]["billing_collector"] = (
        "ok"
        if hasattr(request.app.state, "billing_collector")
        and request.app.state.billing_collector
        else "not initialized"
    )
    health_status["checks"]["telemetry_collector"] = (
        "ok"
        if hasattr(request.app.state, "telemetry_collector")
        and request.app.state.telemetry_collector
        else "not initialized"
    )

    return health_status


@router.get("/health/status")
async def health_status(request: Request):
    """
    Detailed component health with shallow external checks.
    - Redis/DB: Live connectivity (ping)
    - Stripe/Salesforce: Config validation only (no API calls)
    - Circuit breakers: Current state
    """
    components: Dict[str, Any] = {}
    overall = "healthy"

    redis_client = getattr(request.app.state, "redis_client", None)
    close_redis = False

    try:
        if redis_client is None:
            redis_client = aioredis.from_url(
                saas_settings.REDIS_URL, decode_responses=True
            )
            close_redis = True
        redis_start = time.time()
        await redis_client.ping()
        components["redis"] = {
            "status": "healthy",
            "latency_ms": int((time.time() - redis_start) * 1000),
        }
    except Exception as e:
        log.error("Redis health check failed: %s", e, exc_info=True)
        components["redis"] = {"status": "unhealthy", "error": _sanitize_error(e)}
        overall = "unhealthy"
    finally:
        if close_redis and redis_client is not None:
            await redis_client.close()

    try:
        db_start = time.time()
        async with AsyncSessionLocal() as session:
            await session.execute(text("SELECT 1"))
        components["database"] = {
            "status": "healthy",
            "latency_ms": int((time.time() - db_start) * 1000),
        }
    except Exception as e:
        log.error("Database health check failed: %s", e, exc_info=True)
        components["database"] = {"status": "unhealthy", "error": _sanitize_error(e)}
        overall = "unhealthy"

    stripe_key = getattr(saas_settings, "STRIPE_SECRET_KEY", "") or os.getenv(
        "STRIPE_SECRET_KEY", ""
    )
    if stripe_key and stripe_key.startswith(("sk_live_", "sk_test_")):
        components["stripe"] = {
            "status": "healthy",
            "check": "config_valid",
            "circuit": _get_circuit_state("stripe"),
        }
    else:
        components["stripe"] = {
            "status": "degraded",
            "check": "config_missing",
            "circuit": "unknown",
        }
        overall = "degraded" if overall == "healthy" else overall

    try:
        from ..integrations.salesforce import get_active_token_count

        active_tokens = await get_active_token_count()
        components["salesforce"] = {
            "status": "healthy" if active_tokens > 0 else "degraded",
            "check": "token_presence",
            "active_orgs": active_tokens,
            "circuit": _get_circuit_state("salesforce"),
        }
    except Exception:
        components["salesforce"] = {
            "status": "unknown",
            "check": "skipped",
            "circuit": "unknown",
        }

    return {
        "status": overall,
        "components": components,
        "timestamp": datetime.now(timezone.utc).isoformat(),
    }


@router.get("/health/foundrygraph")
async def health_foundrygraph():
    """
    Health check for FoundryGraph BigQuery connectivity.
    Tests that BQ is reachable and the companies_gold table has data.
    """
    from ..services.foundrygraph_bq import check_bq_health

    bq_health = check_bq_health()

    status = "healthy" if bq_health["connected"] and bq_health["sample_count"] > 0 else "unhealthy"
    if bq_health["connected"] and bq_health["sample_count"] == 0:
        status = "degraded"  # Connected but table might be empty

    return {
        "status": status,
        "foundrygraph": bq_health,
        "timestamp": datetime.now(timezone.utc).isoformat(),
    }


# NOTE: Commented out - has missing imports that break router loading
# # api/health.py - Enhanced health checks
# @router.get("/health/dependencies")
# async def check_dependencies(
#     db: AsyncSession = Depends(get_session),
#     redis: aioredis.Redis = Depends(get_redis_queue),
# ):
#     """Check all critical dependencies"""
#
#     health_status = {
#         "database": "unknown",
#         "redis": "unknown",
#         "storage": "unknown",
#         "ml_models": "unknown",
#     }
#
#     # Check database
#     try:
#         await db.execute(text("SELECT 1"))
#         health_status["database"] = "healthy"
#     except Exception as e:
#         health_status["database"] = f"unhealthy: {str(e)}"
#
#     # Check Redis
#     try:
#         await redis.ping()
#         queue_size = await redis.llen("rq:queue:default")
#         health_status["redis"] = f"healthy (queue size: {queue_size})"
#     except Exception as e:
#         health_status["redis"] = f"unhealthy: {str(e)}"
#
#     # Check storage
#     try:
#         storage = get_storage_backend()
#         test_key = f"health-check/{uuid4()}"
#         await storage.save(BytesIO(b"test"), test_key)
#         await storage.delete(test_key)
#         health_status["storage"] = "healthy"
#     except Exception as e:
#         health_status["storage"] = f"unhealthy: {str(e)}"
#
#     # Overall status
#     all_healthy = all(v.startswith("healthy") for v in health_status.values())
#
#     return {
#         "status": "healthy" if all_healthy else "unhealthy",
#         "components": health_status,
#         "timestamp": datetime.utcnow().isoformat(),
#     }
