"""Status / device_context / avatar snapshot builders (live C.2 when possible, else stub)."""

from __future__ import annotations

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

from ...core.version import AGENT_MVP_VERSION
from . import UI_SURFACE
from .avatar_runtime import get_avatar_runtime
from .device_context import build_live_device_context
from .status_runtime import build_live_status


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.total - usage.free) / 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 build_healthz(*, app_version: str = AGENT_MVP_VERSION) -> dict[str, object]:
    return {
        "ok": True,
        "service": "ui_bridge",
        "ui_surface": UI_SURFACE,
        "version": app_version,
        "phase": "C.3",
    }


def build_status_snapshot(*, config_path: Path | None = None, lang: str = "en") -> dict[str, object]:
    live = build_live_status(config_path=config_path, lang=lang)
    if live is not None:
        return live
    return {
        "ok": True,
        "ui_surface": UI_SURFACE,
        "connectivity": "Offline",
        "trust_state": "Unpaired",
        "paired": False,
        "device_id": None,
        "account_email": None,
        "orchestra_label": "Offline / Server Unavailable",
        "orchestra_state": "offline",
        "heartbeat_age_sec": None,
        "backend_base_url": "https://www.iuve.eu",
        "app_version": AGENT_MVP_VERSION,
        "avatar_mode": "Inactive",
        "active_permissions": 0,
        "source": "stub",
        "stub": True,
        "phase": "C.2",
        "computed_at": _utc_now_iso(),
    }


def build_device_context_snapshot(*, config_path: Path | None = None) -> dict[str, object]:
    status = build_status_snapshot(config_path=config_path)
    live = build_live_device_context(
        config_path=config_path,
        trust_fallback=str(status.get("trust_state") or "—"),
    )
    if live is not None:
        return live

    avail_mb, total_mb = _read_meminfo_mb()
    ram_pct = _ram_used_percent(avail_mb, total_mb)
    disk_free = _disk_free_gb()
    disk_pct = _disk_used_percent()

    if avail_mb is not None and total_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 disk_free is not None:
        disk_label = f"{disk_free} GB free"
        if disk_pct is not None:
            disk_label = f"{disk_label} ({disk_pct}%)"
    else:
        disk_label = "—"

    os_label = f"{platform.system()} {platform.release()}"
    fields = {
        "cpu": platform.processor() or platform.machine() or "—",
        "ram": ram_label,
        "disk": disk_label,
        "os": os_label,
        "apps": "—",
        "scan": "—" if status.get("stub") else "just now",
        "trust": str(status.get("trust_state") or "—"),
        "capabilities": "0/8",
        "root": "None active",
    }
    return {
        "ok": True,
        "source": "stub",
        "stub": True,
        "phase": "C.2",
        "fields": fields,
        "metrics": {"cpu": None, "ram": ram_pct, "disk": disk_pct},
        "computed_at": _utc_now_iso(),
    }


def build_avatar_session(*, config_path: Path | None = None) -> dict[str, object]:
    return get_avatar_runtime(config_path).session_snapshot()


def build_avatar_prompt_response(
    payload: dict[str, Any],
    *,
    config_path: Path | None = None,
) -> dict[str, object]:
    return get_avatar_runtime(config_path).submit_prompt(payload)


def build_avatar_prompt_stub(payload: dict[str, Any]) -> dict[str, object]:
    prompt = str(payload.get("prompt") or "").strip()
    if not prompt:
        return {"ok": False, "stub": True, "error": "prompt_required", "message": ""}
    return {
        "ok": True,
        "session_id": None,
        "stub": True,
        "phase": "C.2",
        "message": "No agent config — Avatar live path unavailable. Pair device / set --config.",
        "echo": {
            "prompt": prompt[:500],
            "mode": payload.get("mode") or "Auto",
            "tags": payload.get("tags") or [],
        },
    }


def build_permissions_presets(*, config_path: Path | None = None) -> dict[str, object]:
    """Safe preset list + Connect deep-link (full Permission Center still GTK / Connect)."""
    from iuve_connect_agents.shared.permission_profiles import PROFILE_KEYS

    presets = [{"id": key, "label": key.capitalize()} for key in PROFILE_KEYS]
    presets.append({"id": "full_help", "label": "Full help"})
    connect_url = "https://www.iuve.eu/app/connect"
    active: list[dict[str, object]] = []
    stub = True
    if config_path is not None and config_path.is_file():
        try:
            from ..ui.status_adapter import StatusAdapter

            adapter = StatusAdapter(config_path=config_path)
            active = list(adapter.list_active_action_sessions() or [])
            stub = False
        except Exception:
            stub = True
    return {
        "ok": True,
        "stub": stub,
        "phase": "C.2",
        "presets": presets,
        "active_sessions": len(active),
        "connect_url": connect_url,
        "hint": "Open Permission Center in Connect web or Linux GTK console for full grant UI.",
    }


def build_updates_snapshot(*, config_path: Path | None = None) -> dict[str, object]:
    if config_path is not None and config_path.is_file():
        try:
            from ..ui.status_adapter import StatusAdapter

            adapter = StatusAdapter(config_path=config_path)
            snap = adapter.read_updates_snapshot()
            latest = snap.get("latest_stable_version") or snap.get("recommended_version")
            current = str(snap.get("current_version") or AGENT_MVP_VERSION)
            return {
                "ok": True,
                "stub": False,
                "phase": "C.2",
                "current_version": current,
                "recommended_version": latest,
                "update_available": bool(latest) and str(latest) != current,
                "channel": str(snap.get("channel") or snap.get("update_channel") or "stable"),
                "policy": snap.get("policy"),
            }
        except Exception:
            pass
    return {
        "ok": True,
        "stub": True,
        "phase": "C.2",
        "current_version": AGENT_MVP_VERSION,
        "recommended_version": AGENT_MVP_VERSION,
        "update_available": False,
        "channel": "stable",
    }
