"""
Diagnostic API endpoints
"""

import datetime
import logging

import redis as redis_lib
from fastapi import APIRouter, Request
from fastapi.responses import JSONResponse
from sqlalchemy import text

from app.auth import require_login
from app.config import settings
from app.database import engine

# Set up logging
logger = logging.getLogger(__name__)

_DEFAULT_REDIS_URL = "redis://localhost:6379/0"

router = APIRouter()

# ---------------------------------------------------------------------------
# Unauthenticated probe endpoints for Kubernetes liveness / readiness checks.
# These intentionally skip authentication so that kubelet can reach them
# without credentials.  They live under /diagnostic/healthz/* so that the
# existing authenticated /diagnostic/health endpoint is unaffected.
# ---------------------------------------------------------------------------


@router.get("/diagnostic/healthz/live")
async def liveness_probe() -> JSONResponse:
    """Lightweight liveness probe for Kubernetes.

    Returns **200 OK** as long as the process is running.  Kubernetes uses
    this to decide whether to *restart* the container — it should therefore
    be as cheap as possible and **never** check external dependencies.

    **Authentication:** None (designed for kubelet probes).
    """
    return JSONResponse(content={"status": "ok"}, status_code=200)


@router.get("/diagnostic/healthz/ready")
async def readiness_probe() -> JSONResponse:
    """Readiness probe for Kubernetes.

    Verifies that the application can serve traffic by checking the database
    and Redis.  Kubernetes uses this to decide whether to *route traffic* to
    the pod.

    Returns **200 OK** when all critical subsystems are reachable, or
    **503 Service Unavailable** when the database is down.

    **Authentication:** None (designed for kubelet probes).
    """
    checks: dict[str, dict[str, str]] = {}
    db_ok = False

    # ── Database check ─────────────────────────────────────────────────
    try:
        with engine.connect() as conn:
            conn.execute(text("SELECT 1"))
        checks["database"] = {"status": "ok"}
        db_ok = True
    except Exception as exc:
        logger.warning("Readiness probe: database check failed: %s", exc)
        checks["database"] = {"status": "error", "detail": str(exc)}

    # ── Redis check ────────────────────────────────────────────────────
    try:
        redis_url = settings.redis_url or _DEFAULT_REDIS_URL
        r = redis_lib.from_url(redis_url, socket_connect_timeout=2, socket_timeout=2)
        r.ping()
        checks["redis"] = {"status": "ok"}
    except Exception as exc:
        logger.warning("Readiness probe: Redis check failed: %s", exc)
        checks["redis"] = {"status": "error", "detail": str(exc)}

    http_status = 503 if not db_ok else 200
    overall = "ready" if db_ok else "not_ready"
    return JSONResponse(content={"status": overall, "checks": checks}, status_code=http_status)


@router.get("/diagnostic/health")
@require_login
async def health_check(request: Request):
    """
    System health endpoint for monitoring tools (Grafana, Uptime Kuma, etc.).

    Checks database connectivity and Redis availability and returns a
    machine-readable summary that monitoring systems can scrape.

    **Authentication:** Required (no-op when AUTH_ENABLED=False)

    **Response (200 OK) – all subsystems healthy:**
    ```json
    {
      "status": "healthy",
      "version": "1.2.3",
      "timestamp": "2024-01-15T10:30:00+00:00",
      "checks": {
        "database": {"status": "ok"},
        "redis":    {"status": "ok"}
      }
    }
    ```

    **Response (200 OK) – one or more subsystems degraded:**
    ```json
    {
      "status": "degraded",
      "version": "1.2.3",
      "timestamp": "2024-01-15T10:30:00+00:00",
      "checks": {
        "database": {"status": "ok"},
        "redis":    {"status": "error", "detail": "Connection refused"}
      }
    }
    ```

    The outer ``status`` field is always one of:
    - ``"healthy"``  – all checks passed
    - ``"degraded"`` – at least one non-critical check failed
    - ``"unhealthy"`` – a critical check failed (currently: database)
    """
    timestamp = datetime.datetime.now(datetime.timezone.utc).isoformat()
    checks: dict[str, dict[str, str]] = {}

    # ── Database check ─────────────────────────────────────────────────────
    db_ok = False
    try:
        with engine.connect() as conn:
            conn.execute(text("SELECT 1"))
        checks["database"] = {"status": "ok"}
        db_ok = True
    except Exception as exc:
        logger.warning("Health check: database probe failed: %s", exc)
        checks["database"] = {"status": "error", "detail": str(exc)}

    # ── Redis check ────────────────────────────────────────────────────────
    try:
        redis_url = settings.redis_url or _DEFAULT_REDIS_URL
        r = redis_lib.from_url(redis_url, socket_connect_timeout=2, socket_timeout=2)
        r.ping()
        checks["redis"] = {"status": "ok"}
    except Exception as exc:
        logger.warning("Health check: Redis probe failed: %s", exc)
        checks["redis"] = {"status": "error", "detail": str(exc)}

    # ── Overall status ─────────────────────────────────────────────────────
    if not db_ok:
        overall = "unhealthy"
    elif any(v.get("status") != "ok" for v in checks.values()):
        overall = "degraded"
    else:
        overall = "healthy"

    http_status = 503 if overall == "unhealthy" else 200

    payload = {
        "status": overall,
        "version": settings.version,
        "timestamp": timestamp,
        "checks": checks,
    }

    return JSONResponse(content=payload, status_code=http_status)


@router.post("/diagnostic/test-notification")
@require_login
async def test_notification(request: Request):
    # Add request_time to request.state
    import datetime

    request.state.request_time = datetime.datetime.now(datetime.timezone.utc).isoformat()
    """
    Send a test notification through all configured notification channels
    """
    from app.utils.notification import send_notification

    try:
        notification_urls = getattr(settings, "notification_urls", [])
        if not notification_urls:
            return {
                "status": "warning",
                "message": "No notification services configured. Add notification URLs to your configuration.",
            }

        # Send a test notification
        hostname = settings.external_hostname or "Document Processor"
        result = send_notification(
            title=f"Test Notification from {hostname}",
            message=(
                f"This is a test notification sent at {request.state.request_time}. "
                "If you're receiving this, notifications are working!"
            ),
            notification_type="success",
            tags=["test", "notification", "diagnostic"],
        )

        if result:
            logger.info("Test notification sent successfully")
            return {
                "status": "success",
                "message": f"Test notification sent successfully to {len(notification_urls)} service(s)",
                "services_count": len(notification_urls),
            }
        else:
            logger.warning("Test notification send attempt returned False")
            return {
                "status": "error",
                "message": "Failed to send test notification. Check application logs for details.",
            }

    except Exception as e:
        logger.exception(f"Error sending test notification: {e}")
        return {"status": "error", "message": f"Error sending notification: {str(e)}"}
