from __future__ import annotations
import json
from datetime import datetime, timezone
from pathlib import Path

from neurotron.logbus import logbus
from .neurotron_config import (
    NEUROTRON_DATASET_PATH,
    NEUROTRON_HISTORY_KEEP,
    NEUROTRON_DIAG_SCHEMA,
    HOMEOSTASIS_CPU_WARN,
    HOMEOSTASIS_CPU_ALERT,
    HOMEOSTASIS_MEM_WARN,
    HOMEOSTASIS_MEM_ALERT,
    HOMEOSTASIS_LOAD_WARN,
    HOMEOSTASIS_LOAD_ALERT,
)
from .perception import Perception


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


class AutoDiagnostic:
    """
    Diagnóstico interno do Neurotron.
    Sempre devolve chaves padronizadas:
        cpu, mem, load1
    Nunca lança exceções — segurança máxima.
    """

    def __init__(self, runtime_dir: str, log_dir: str):
        self.runtime_dir = Path(runtime_dir)
        self.log_dir = Path(log_dir)

        self.data_dir = Path(NEUROTRON_DATASET_PATH)
        self.data_dir.mkdir(parents=True, exist_ok=True)

        self.last_file = self.data_dir / "last_diagnostic.json"
        self.telemetry_file = self.data_dir / "telemetry.json"

        self.perception = Perception()

    # ----------------------------------------------------------------------
    def _load_previous(self):
        try:
            if self.last_file.exists():
                return json.loads(self.last_file.read_text())
        except Exception as e:
            logbus.debug(f"[diag.warn] falha ao ler último diagnóstico: {e}")
        return None

    # ----------------------------------------------------------------------
    def _save_current(self, payload):
        prev = self._load_previous()
        history = []

        if prev:
            history = prev.get("history", [])
            history.append({
                "timestamp": prev.get("timestamp"),
                "cpu": prev.get("cpu"),
                "mem": prev.get("mem"),
                "load1": prev.get("load1"),
                "state": prev.get("state", "UNKNOWN"),
            })
            history = history[-NEUROTRON_HISTORY_KEEP:]

        payload["history"] = history

        try:
            self.last_file.write_text(json.dumps(payload, indent=2))
        except Exception as e:
            logbus.debug(f"[diag.error] falha ao gravar diagnóstico: {e}")

    # ----------------------------------------------------------------------
    def _classify_state(self, cpu, mem, l1):
        try:
            cpu = float(cpu)
            mem = float(mem)
            l1 = float(l1)
        except Exception:
            return "UNKNOWN"

        if cpu >= HOMEOSTASIS_CPU_ALERT or mem >= HOMEOSTASIS_MEM_ALERT or l1 >= HOMEOSTASIS_LOAD_ALERT:
            return "CRITICAL"

        if cpu >= HOMEOSTASIS_CPU_WARN or mem >= HOMEOSTASIS_MEM_WARN or l1 >= HOMEOSTASIS_LOAD_WARN:
            return "ALERT"

        return "STABLE"

    # ----------------------------------------------------------------------
    def run_exam(self):
        """
        Produz um snapshot canónico com chaves:
           cpu, mem, load1
        """
        snap = self.perception.snapshot()

        cpu  = snap.get("cpu_percent", "?")
        mem  = snap.get("mem_percent", "?")
        load = snap.get("loadavg", ["?", "?", "?"])

        if isinstance(load, list) and load:
            l1 = load[0]
        else:
            l1 = "?"

        # chaves normalizadas
        payload = {
            "schema": NEUROTRON_DIAG_SCHEMA,
            "timestamp": _now_iso(),
            "cpu": cpu,
            "mem": mem,
            "load1": l1,
            "loadavg": load,
            "state": self._classify_state(cpu, mem, l1),
            "env": {
                "user": snap.get("env_user"),
                "term": snap.get("env_term"),
            },
        }

        self._save_current(payload)
        self._update_telemetry(payload)

        logbus.debug(
            f"[diag] estado={payload['state']} cpu={cpu} mem={mem} load1={l1}"
        )

        return payload["state"], payload

    # ----------------------------------------------------------------------
    def _update_telemetry(self, payload):
        try:
            tele = []
            if self.telemetry_file.exists():
                tele = json.loads(self.telemetry_file.read_text() or "[]")

            tele.append({
                "timestamp": payload["timestamp"],
                "cpu": payload["cpu"],
                "mem": payload["mem"],
                "load1": payload["load1"],
                "state": payload["state"],
            })

            tele = tele[-128:]
            self.telemetry_file.write_text(json.dumps(tele, indent=2))

        except Exception as e:
            logbus.debug(f"[diag.warn] falha ao atualizar telemetria: {e}")
