"""
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

from src.runtime_topology import inspect_runtime_config, inspect_runtime_processes

# ROOT now resolved via frozen_path (PyInstaller-safe)
from frozen_path import APP_ROOT as ROOT
# LOG_DIR now resolved via frozen_path
from frozen_path import LOG_DIR as LOG_DIR


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_api_key() -> dict[str, Any]:
    """Check if DeepSeek API key is configured."""
    api_key = os.environ.get("DEEPSEEK_API_KEY", "")
    if not api_key:
        try:
            from src.llm.config import load_llm_providers
            providers = load_llm_providers()
            deepseek = providers.get("deepseek", {})
            api_key = deepseek.get("apiKey", "")
        except Exception:
            pass
    if not api_key:
        try:
            import config_manager
            app_config = config_manager.load_app_config()
            api_key = app_config.get("DEEPSEEK_API_KEY", "")
        except Exception:
            pass
    has_key = bool(api_key and api_key != "YOUR_DEEPSEEK_API_KEY_HERE")
    return {
        "status": "CONFIGURED" if has_key else "NOT_CONFIGURED",
        "provider": "deepseek",
        "get_key_url": "https://platform.deepseek.com/api_keys",
    }


def _probe_payment() -> dict[str, Any]:
    return {
        "status": "MANUAL",
        "provider": "wechat_qq",
        "contact_wechat": "goldautotrade",
        "contact_qq": "goldautotrade",
        "contact_email": "support@goldauto.top",
        "website": "https://license.goldauto.top/license",
    }


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 = LOG_DIR / "gold_trader.pid"
    if pid_path.exists():
        try:
            pid = int(pid_path.read_text(encoding="utf-8").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 = LOG_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_runtime_topology() -> dict[str, Any]:
    return inspect_runtime_processes(ROOT)


def _probe_runtime_config() -> dict[str, Any]:
    return inspect_runtime_config(ROOT)


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(),
        "api_key": _probe_api_key(),
        "trading": _probe_trading(),
        "runtime_topology": _probe_runtime_topology(),
        "runtime_config": _probe_runtime_config(),
        "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 ("WARNING", "NOT_CONFIGURED", "NO_BACKUPS", "IDLE", "STOPPED", "UNLICENSED", "TRIAL"):
            summary["warning"] += 1
            alert = {"subsystem": name, "level": "WARNING", "status": status}
            message = str(p.get("message", "") or "").strip()
            if message:
                alert["message"] = message
            alerts.append(alert)
        elif status in ("ERROR", "FAIL", "EXPIRED", "REVOKED", "BLOCKED"):
            summary["error"] += 1
            alert = {"subsystem": name, "level": "ERROR", "status": status}
            message = str(p.get("message", "") or "").strip()
            if message:
                alert["message"] = message
            alerts.append(alert)
        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()
