"""
System health dashboard — aggregates status from ALL subsystems into one endpoint.

Called by: GET /health/full in control_api.py
Displayed in: React GUI dashboard

Returns a single JSON with every subsystem's status, metrics, and alerts.
"""
from __future__ import annotations

import os
import time
from datetime import datetime, timezone
from pathlib import Path
from typing import Any

ROOT = Path(__file__).resolve().parent.parent.parent
LOGS_DIR = ROOT / "logs"


def _now() -> str:
    return datetime.now(timezone.utc).isoformat()


# ─── Individual subsystem probes ───────────────────────────────────

def _probe_license() -> dict[str, Any]:
    try:
        from src.license.validator import get_license_status
        return get_license_status()
    except Exception as e:
        return {"status": "ERROR", "error": str(e)}


def _probe_compliance() -> dict[str, Any]:
    try:
        from src.compliance.disclaimers import get_compliance_status
        return get_compliance_status()
    except Exception as e:
        return {"status": "ERROR", "error": str(e)}


def _probe_onboarding() -> dict[str, Any]:
    try:
        from src.onboarding.wizard import get_progress
        return get_progress()
    except Exception as e:
        return {"status": "ERROR", "error": str(e)}


def _probe_backup() -> dict[str, Any]:
    try:
        from ops.auto_backup import list_backups as _list, BACKUP_DIR, MAX_BACKUPS
        backups = _list()
        latest = backups[0] if backups else None
        return {
            "status": "OK" if backups else "NO_BACKUPS",
            "total_backups": len(backups),
            "latest": latest,
            "max_retention": MAX_BACKUPS,
            "backup_dir": str(BACKUP_DIR),
        }
    except Exception as e:
        return {"status": "ERROR", "error": str(e)}


def _probe_email() -> dict[str, Any]:
    try:
        from src.notify.emailer import SMTP_HOST, SMTP_USER, DEFAULT_RECIPIENTS, QUEUE_FILE
        configured = bool(SMTP_USER)
        queue_size = 0
        if QUEUE_FILE.exists():
            queue_size = len(QUEUE_FILE.read_text(encoding="utf-8").splitlines())
        return {
            "status": "CONFIGURED" if configured else "NOT_CONFIGURED",
            "smtp_host": SMTP_HOST,
            "from": SMTP_USER or "(not set)",
            "recipients": DEFAULT_RECIPIENTS or "(not set)",
            "queued_emails": queue_size,
        }
    except Exception as e:
        return {"status": "ERROR", "error": str(e)}


def _probe_payment() -> dict[str, Any]:
    try:
        from src.payment.stripe import STRIPE_SECRET_KEY
        return {
            "status": "LIVE" if STRIPE_SECRET_KEY else "MOCK",
            "provider": "stripe",
        }
    except Exception as e:
        return {"status": "ERROR", "error": str(e)}


def _probe_trading() -> dict[str, Any]:
    """Read trading status from runtime state + ledger."""
    result: dict[str, Any] = {"status": "UNKNOWN", "mode": "unknown"}

    # Check if runtime has trading info
    runtime_path = ROOT / "tenants" / "default" / "ops" / "runtime_state.json"
    try:
        import json
        if runtime_path.exists():
            state = json.loads(runtime_path.read_text(encoding="utf-8"))
            result["mode"] = state.get("promotion_mode", "unknown")
            result["runtime_mode"] = state.get("runtime_mode", "unknown")
    except Exception:
        pass

    # Check daemon PID
    pid_path = LOGS_DIR / "gold_trader.pid"
    if pid_path.exists():
        try:
            pid = int(pid_path.read_text().strip())
            os.kill(pid, 0)  # signal 0 = check if exists
            result["daemon"] = "RUNNING"
            result["daemon_pid"] = pid
        except (ValueError, OSError):
            result["daemon"] = "STOPPED"
    else:
        result["daemon"] = "STOPPED"

    # Recent trades from ledger
    ledger_path = LOGS_DIR / "decision_ledger.ndjson"
    if ledger_path.exists():
        try:
            lines = ledger_path.read_text(encoding="utf-8").splitlines()
            recent = [l for l in lines[-20:] if l.strip()]
            result["recent_events"] = len(recent)
            result["ledger_size_lines"] = len(lines)
        except Exception:
            pass

    result["status"] = "ACTIVE" if result.get("daemon") == "RUNNING" else "IDLE"
    return result


def _probe_system() -> dict[str, Any]:
    """Basic system resource info."""
    import platform
    return {
        "hostname": platform.node(),
        "platform": platform.platform(),
        "python": platform.python_version(),
        "pid": os.getpid(),
        "cwd": str(Path.cwd()),
    }


def _probe_disk() -> dict[str, Any]:
    """Disk usage for project directory."""
    try:
        total = 0
        for f in ROOT.rglob("*"):
            if f.is_file():
                try:
                    total += f.stat().st_size
                except OSError:
                    pass
        return {"project_size_bytes": total, "project_size_mb": round(total / 1024 / 1024, 1)}
    except Exception as e:
        return {"error": str(e)}


# ─── Aggregation ───────────────────────────────────────────────────

def get_full_health(include_disk: bool = False) -> dict[str, Any]:
    """
    Run all subsystem probes and return aggregated health report.

    Returns:
      {
        "ok": true/false,
        "timestamp": "...",
        "subsystems": {
          "license": {...},
          "compliance": {...},
          "onboarding": {...},
          "backup": {...},
          "email": {...},
          "payment": {...},
          "trading": {...},
          "system": {...},
          "disk": {...}  (optional)
        },
        "alerts": [...],
        "summary": {"total": N, "ok": N, "warning": N, "error": N}
      }
    """
    ts = _now()

    probes = {
        "license": _probe_license(),
        "compliance": _probe_compliance(),
        "onboarding": _probe_onboarding(),
        "backup": _probe_backup(),
        "email": _probe_email(),
        "payment": _probe_payment(),
        "trading": _probe_trading(),
        "system": _probe_system(),
    }
    if include_disk:
        probes["disk"] = _probe_disk()

    # Classify each subsystem
    alerts: list[dict[str, str]] = []
    summary = {"total": len(probes), "ok": 0, "warning": 0, "error": 0}

    for name, p in probes.items():
        status = str(p.get("status", "UNKNOWN")).upper()
        if status in ("ACTIVE", "OK", "CONFIGURED", "LIVE", "MOCK", "RUNNING", "PASS"):
            summary["ok"] += 1
        elif status in ("NOT_CONFIGURED", "NO_BACKUPS", "IDLE", "STOPPED", "UNLICENSED", "TRIAL"):
            summary["warning"] += 1
            alerts.append({"subsystem": name, "level": "WARNING", "status": status})
        elif status in ("ERROR", "FAIL", "EXPIRED", "REVOKED", "BLOCKED"):
            summary["error"] += 1
            alerts.append({"subsystem": name, "level": "ERROR", "status": status})
        else:
            summary["warning"] += 1

    overall_ok = summary["error"] == 0

    return {
        "ok": overall_ok,
        "timestamp": ts,
        "uptime_seconds": round(time.time() - _start_time, 1),
        "subsystems": probes,
        "alerts": alerts,
        "summary": summary,
    }


# Track when this module was first loaded (proxy for process start)
_start_time = time.time()
