"""
Phase 88: Network Launcher — Launch Swarm V2 on the Live brynq.ai Network.

Storage:
  state/broker/network/status.json
  state/broker/network/events.jsonl
"""

import importlib
import json
import logging
import uuid
from datetime import datetime, timezone
from pathlib import Path
from typing import Any, Callable, Dict, List, Optional

from brynq.server import BROKER_DIR, _write_json_sync, _read_jsonl_sync, _append_jsonl_sync

logger = logging.getLogger(__name__)

# ── Paths ──────────────────────────────────────────────────────────────────

NETWORK_DIR = BROKER_DIR / "network"
STATUS_FILE = NETWORK_DIR / "status.json"
EVENTS_FILE = NETWORK_DIR / "events.jsonl"

NETWORK_DIR.mkdir(parents=True, exist_ok=True)

# ── In-memory state ─────────────────────────────────────────────────────

_subsystems: Dict[str, Dict[str, Any]] = {}
_network_state: Dict[str, Any] = {
    "initialized": False,
    "started_at": None,
    "config": {},
}

# Critical modules that must import cleanly for the network to launch.
CRITICAL_MODULES = [
    "brynq.server",
    "brynq.event_bus",
    "brynq.health_monitor",
    "brynq.knowledge_mcp",
    "brynq.swarm_state_machine",
]


def reset_state() -> None:
    """Reset in-memory state. Used by tests."""
    global _subsystems, _network_state
    _subsystems = {}
    _network_state = {"initialized": False, "started_at": None, "config": {}}


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


def _log_event(event: dict) -> None:
    event.setdefault("timestamp", _now_iso())
    event.setdefault("id", uuid.uuid4().hex[:12])
    _append_jsonl_sync(EVENTS_FILE, event)


def _save_status(status: dict) -> None:
    _write_json_sync(STATUS_FILE, status)


# ── Public API ───────────────────────────────────────────────────────────

def register_subsystem(name: str, health_check_fn: Callable) -> dict:
    """Register a subsystem for monitoring. health_check_fn -> {"healthy": bool, "detail": str}."""
    _subsystems[name] = {
        "name": name, "health_check_fn": health_check_fn,
        "registered_at": _now_iso(), "last_check": None, "last_status": None,
    }
    _log_event({"event": "subsystem_registered", "subsystem": name})
    return {"registered": name, "total_subsystems": len(_subsystems)}


def initialize_network(config: Optional[dict] = None) -> dict:
    """Bootstrap all Swarm V2 subsystems."""
    global _network_state
    cfg = config or {}
    _network_state = {
        "initialized": True,
        "started_at": _now_iso(),
        "config": cfg,
    }

    # Auto-register core subsystems with simple health checks
    core_subs = cfg.get("subsystems", [
        "event_bus", "health_monitor", "knowledge_mcp",
        "swarm_state_machine", "network_launcher",
    ])
    registered = []
    for sub_name in core_subs:
        if sub_name not in _subsystems:
            register_subsystem(sub_name, lambda n=sub_name: {
                "healthy": True, "detail": f"{n} running"
            })
            registered.append(sub_name)

    status = {
        "state": "running",
        "started_at": _network_state["started_at"],
        "subsystems": list(_subsystems.keys()),
        "config": cfg,
    }
    _save_status(status)
    _log_event({"event": "network_initialized",
                "subsystems": list(_subsystems.keys()),
                "config_keys": list(cfg.keys())})

    return {
        "status": "initialized",
        "subsystems_registered": list(_subsystems.keys()),
        "started_at": _network_state["started_at"],
    }


def get_network_status() -> dict:
    """Comprehensive health of all subsystems."""
    if not _network_state.get("initialized"):
        return {"status": "not_initialized", "subsystems": []}

    sub_statuses, healthy_count = [], 0
    for name, sub in _subsystems.items():
        result = _run_health_check(sub)
        if result.get("healthy"):
            healthy_count += 1
        sub_statuses.append({"name": name, **result})

    total = len(_subsystems)
    health_score = (healthy_count / total * 100) if total > 0 else 0

    status = {"status": "running" if _network_state["initialized"] else "stopped",
              "started_at": _network_state["started_at"], "subsystems": sub_statuses,
              "total_subsystems": total, "healthy_subsystems": healthy_count,
              "health_score": round(health_score, 1)}
    _save_status(status)
    return status


def _run_health_check(sub: dict) -> dict:
    """Run a single subsystem health check, updating last_check/last_status."""
    try:
        result = sub["health_check_fn"]()
    except Exception as e:
        result = {"healthy": False, "detail": str(e)}
    sub["last_check"] = _now_iso()
    sub["last_status"] = result
    return result


def check_all_subsystems() -> dict:
    """Run health checks on every registered subsystem."""
    results = {name: _run_health_check(sub) for name, sub in _subsystems.items()}
    healthy = sum(1 for r in results.values() if r.get("healthy"))
    return {"checked": len(results), "healthy": healthy,
            "unhealthy": len(results) - healthy, "results": results}


def get_subsystem_status(name: str) -> dict:
    """Individual subsystem health."""
    sub = _subsystems.get(name)
    if sub is None:
        return {"error": f"Subsystem '{name}' not registered"}
    check = _run_health_check(sub)
    return {"name": name, "registered_at": sub["registered_at"], **check}


def shutdown_network(reason: str = "") -> dict:
    """Graceful shutdown of all subsystems."""
    global _network_state
    if not _network_state.get("initialized"):
        return {"status": "already_stopped"}

    shutdown_at = _now_iso()
    subs_stopped = list(_subsystems.keys())
    _log_event({"event": "network_shutdown", "reason": reason,
                "subsystems": subs_stopped})

    _network_state = {"initialized": False, "started_at": None, "config": {}}
    _subsystems.clear()

    status = {"state": "stopped", "stopped_at": shutdown_at, "reason": reason}
    _save_status(status)
    return {
        "status": "shutdown",
        "stopped_at": shutdown_at,
        "subsystems_stopped": subs_stopped,
        "reason": reason,
    }


def get_network_stats() -> dict:
    """Aggregate stats: modules loaded, uptime, events processed, etc."""
    events = _read_jsonl_sync(EVENTS_FILE)
    uptime_seconds = 0
    if _network_state.get("started_at"):
        try:
            started = datetime.fromisoformat(_network_state["started_at"])
            uptime_seconds = (datetime.now(timezone.utc) - started).total_seconds()
        except (ValueError, TypeError):
            pass

    return {
        "initialized": _network_state.get("initialized", False),
        "modules_loaded": len(_subsystems),
        "uptime_seconds": round(uptime_seconds, 1),
        "events_processed": len(events),
        "subsystems": list(_subsystems.keys()),
        "started_at": _network_state.get("started_at"),
    }


def run_startup_diagnostics() -> dict:
    """Verify critical modules import, directories exist, config valid."""
    results = {"modules": {}, "directories": {}, "overall": "pass"}

    # Check critical module imports
    for mod_name in CRITICAL_MODULES:
        try:
            importlib.import_module(mod_name)
            results["modules"][mod_name] = "ok"
        except Exception as e:
            results["modules"][mod_name] = f"FAIL: {e}"
            results["overall"] = "fail"

    # Check critical directories
    critical_dirs = {
        "broker_dir": BROKER_DIR,
        "network_dir": NETWORK_DIR,
    }
    for label, dirpath in critical_dirs.items():
        if dirpath.exists():
            results["directories"][label] = "ok"
        else:
            results["directories"][label] = "MISSING"
            results["overall"] = "fail"

    # Validate config is present
    if _network_state.get("initialized"):
        results["config_status"] = "loaded"
    else:
        results["config_status"] = "not_initialized"

    _log_event({"event": "diagnostics_run", "overall": results["overall"]})
    return results
