"""Device Context right-rail builder (GTK parity, no GTK imports)."""

from __future__ import annotations

import platform
import shutil
from datetime import datetime, timezone
from pathlib import Path
from typing import Any


def _utc_now_iso() -> str:
    return datetime.now(tz=timezone.utc).replace(microsecond=0).isoformat().replace("+00:00", "Z")


def _read_meminfo_mb() -> tuple[int | None, int | None]:
    meminfo = Path("/proc/meminfo")
    if not meminfo.is_file():
        return None, None
    total_kb = None
    avail_kb = None
    for line in meminfo.read_text(encoding="utf-8", errors="ignore").splitlines():
        if line.startswith("MemTotal:"):
            total_kb = int(line.split()[1])
        elif line.startswith("MemAvailable:"):
            avail_kb = int(line.split()[1])
    if total_kb is None or avail_kb is None:
        return None, None
    return avail_kb // 1024, total_kb // 1024


def _disk_free_gb() -> float | None:
    try:
        usage = shutil.disk_usage(Path.home())
        return round(usage.free / (1024**3), 1)
    except OSError:
        return None


def _disk_used_percent() -> int | None:
    try:
        usage = shutil.disk_usage(Path.home())
        if usage.total <= 0:
            return None
        return int(round(100.0 * usage.used / usage.total))
    except OSError:
        return None


def _ram_used_percent(avail_mb: int | None, total_mb: int | None) -> int | None:
    if avail_mb is None or total_mb is None or total_mb <= 0:
        return None
    used = max(0, total_mb - avail_mb)
    return int(round(100.0 * used / total_mb))


def _cpu_usage_percent(state: dict[str, Any]) -> int | None:
    """Rough /proc/stat delta; needs two samples across refreshes."""
    stat = Path("/proc/stat")
    if not stat.is_file():
        return None
    try:
        line = stat.read_text(encoding="utf-8").splitlines()[0]
        parts = line.split()
        if parts[0] != "cpu":
            return None
        nums = [int(x) for x in parts[1:8]]
        idle = nums[3] + nums[4]
        total = sum(nums)
        prev_total = state.get("_cpu_total")
        prev_idle = state.get("_cpu_idle")
        state["_cpu_total"] = total
        state["_cpu_idle"] = idle
        if prev_total is None or prev_idle is None:
            return None
        total_delta = total - int(prev_total)
        idle_delta = idle - int(prev_idle)
        if total_delta <= 0:
            return None
        busy = max(0.0, (total_delta - idle_delta) / float(total_delta))
        return max(0, min(100, int(round(busy * 100))))
    except Exception:
        return None


def _format_scan_age(scanned_at: Any) -> str:
    raw = str(scanned_at or "").strip()
    if not raw:
        return "—"
    try:
        ts = datetime.fromisoformat(raw.replace("Z", "+00:00"))
        age = datetime.now(tz=timezone.utc) - ts.astimezone(timezone.utc)
        secs = int(age.total_seconds())
        if secs < 90:
            return "just now"
        if secs < 3600:
            return f"{secs // 60}m ago"
        return f"{max(1, secs // 3600)}h ago"
    except Exception:
        return raw[:32]


_METRIC_STATE: dict[str, Any] = {}


def build_live_device_context(*, config_path: Path | None, trust_fallback: str = "—") -> dict[str, object] | None:
    if config_path is None or not config_path.is_file():
        return None
    try:
        from ..ui.status_adapter import StatusAdapter

        adapter = StatusAdapter(config_path=config_path)
        dash = adapter.read_dashboard_snapshot()
        caps = adapter.read_capability_snapshot()
        granted_ui, total_ui = adapter.read_active_ui_grant_counts()
        profile = adapter.read_device_capability_profile()
        root_enabled = bool(caps.get("root_operations", {}).get("enabled", False))

        cpu_info = profile.get("cpu") if isinstance(profile.get("cpu"), dict) else {}
        memory = profile.get("memory") if isinstance(profile.get("memory"), dict) else {}
        disk_info = profile.get("disk") if isinstance(profile.get("disk"), dict) else {}
        os_info = profile.get("os") if isinstance(profile.get("os"), dict) else {}

        cpu_pct = _cpu_usage_percent(_METRIC_STATE)
        avail_mb = memory.get("available_mb")
        total_mb = memory.get("total_mb")
        if avail_mb is None or total_mb is None:
            avail_mb, total_mb = _read_meminfo_mb()
        ram_pct = _ram_used_percent(
            int(avail_mb) if avail_mb is not None else None,
            int(total_mb) if total_mb is not None else None,
        )
        disk_pct = _disk_used_percent()
        free_gb = disk_info.get("free_gb")
        if free_gb is None:
            free_gb = _disk_free_gb()

        cpu_model = str(cpu_info.get("model") or "").strip()
        if cpu_model and cpu_pct is not None:
            cpu_label = f"{cpu_model[:28]} ({cpu_pct}%)"
        elif cpu_model:
            cpu_label = cpu_model[:36]
        else:
            cpu_label = platform.processor() or platform.machine() or "—"
            if cpu_pct is not None:
                cpu_label = f"{cpu_label} ({cpu_pct}%)"

        if total_mb is not None and avail_mb is not None:
            ram_label = f"{avail_mb}/{total_mb} MB"
            if ram_pct is not None:
                ram_label = f"{ram_label} ({ram_pct}%)"
        else:
            ram_label = "—"

        if free_gb is not None:
            disk_label = f"{free_gb} GB free"
            if disk_pct is not None:
                disk_label = f"{disk_label} ({disk_pct}%)"
        else:
            disk_label = "—"

        if os_info:
            os_label = f"{os_info.get('name', '?')} {os_info.get('version', '')}".strip()[:40]
        else:
            os_label = f"{platform.system()} {platform.release()}"

        apps_count = profile.get("applications_count")
        fields = {
            "cpu": cpu_label,
            "ram": ram_label,
            "disk": disk_label,
            "os": os_label,
            "apps": str(apps_count) if apps_count is not None else "—",
            "scan": _format_scan_age(profile.get("scanned_at")),
            "trust": str(dash.get("trust_state") or trust_fallback or "—"),
            "capabilities": f"{granted_ui}/{total_ui}",
            "root": "Enabled" if root_enabled else "None active",
        }
        return {
            "ok": True,
            "source": "live",
            "stub": False,
            "phase": "C.2",
            "fields": fields,
            "metrics": {"cpu": cpu_pct, "ram": ram_pct, "disk": disk_pct},
            "computed_at": _utc_now_iso(),
        }
    except Exception:
        return None
