"""Device Context Model (DCM) — canonical device path/session snapshot for planners."""

from __future__ import annotations

import contextvars
import locale
import os
import platform
from contextlib import contextmanager
from datetime import datetime, timezone
from pathlib import Path
from typing import Any, Iterator

DCM_SCHEMA_VERSION = "0.2.2.64"

_PATH_KEYS = ("desktop", "documents", "downloads", "iuve_workspace", "home", "pictures", "music", "videos")

_planning_dcm: contextvars.ContextVar[dict[str, Any] | None] = contextvars.ContextVar(
    "planning_dcm",
    default=None,
)


def get_planning_dcm() -> dict[str, Any] | None:
    """DCM injected for the current planning call (server or agent)."""
    return _planning_dcm.get()


@contextmanager
def planning_dcm_scope(dcm: dict[str, Any] | None) -> Iterator[None]:
    token = _planning_dcm.set(dict(dcm) if isinstance(dcm, dict) and dcm else None)
    try:
        yield
    finally:
        _planning_dcm.reset(token)


def _detect_locale() -> str:
    for getter in (locale.getlocale, locale.getdefaultlocale):
        try:
            value = getter()
            if isinstance(value, tuple):
                value = value[0]
            code = str(value or "").strip()
            if code and code != "C":
                return code.replace("_", "-")
        except Exception:
            continue
    return str(os.environ.get("LANG") or os.environ.get("LC_ALL") or "en-US").split(".")[0].replace("_", "-")


def _detect_session() -> str:
    if os.environ.get("WAYLAND_DISPLAY"):
        return "wayland"
    if os.environ.get("DISPLAY"):
        return "x11"
    if platform.system().lower() == "windows":
        return "windows_session"
    return "unknown"


def _detect_desktop_environment() -> str:
    for key in ("XDG_CURRENT_DESKTOP", "DESKTOP_SESSION"):
        value = str(os.environ.get(key) or "").strip().lower()
        if value:
            return value.split(":", 1)[0]
    if platform.system().lower() == "windows":
        return "windows_shell"
    return "unknown"


def _windows_known_paths() -> dict[str, str]:
    profile = Path(os.environ.get("USERPROFILE") or Path.home())
    return {
        "desktop": str(profile / "Desktop"),
        "documents": str(profile / "Documents"),
        "downloads": str(profile / "Downloads"),
        "home": str(profile),
        "iuve_workspace": str(profile / "IuVeWorkspace"),
        "pictures": str(profile / "Pictures"),
        "music": str(profile / "Music"),
        "videos": str(profile / "Videos"),
    }


def _macos_known_paths() -> dict[str, str]:
    home = Path.home()
    return {
        "desktop": str(home / "Desktop"),
        "documents": str(home / "Documents"),
        "downloads": str(home / "Downloads"),
        "home": str(home),
        "iuve_workspace": str(home / "IuVeWorkspace"),
        "pictures": str(home / "Pictures"),
        "music": str(home / "Music"),
        "videos": str(home / "Movies"),
    }


def _linux_paths_from_resolver() -> dict[str, str]:
    from iuve_connect_agents.desktop.active.capability_resolver import resolve_xdg_folder, resolve_workspace_path

    paths: dict[str, str] = {}
    for scope in _PATH_KEYS:
        if scope == "iuve_workspace":
            paths[scope] = str(resolve_workspace_path().expanduser())
            continue
        folder = resolve_xdg_folder(scope)  # type: ignore[arg-type]
        if folder is not None:
            paths[scope] = str(folder.expanduser())
    if "home" not in paths:
        paths["home"] = str(Path.home())
    if "iuve_workspace" not in paths:
        paths["iuve_workspace"] = str(Path.home() / "IuVeWorkspace")
    return paths


def build_device_context_snapshot(
    *,
    device_id: str = "",
    trust_state: str = "",
    routing_mode: str | None = None,
    apps_indexed: int = 0,
    installed_apps: list[dict[str, Any]] | None = None,
) -> dict[str, Any]:
    """Build canonical DCM JSON from the paired device (agent-side refresh)."""
    from iuve_connect_agents.desktop.active.capability_resolver import (
        resolve_workspace_path,
        resolve_workspace_routing_mode,
    )

    os_family = platform.system().lower()
    if os_family == "darwin":
        os_family = "macos"
    mode = routing_mode or resolve_workspace_routing_mode(trust_state=trust_state)
    if os_family == "windows":
        paths = _windows_known_paths()
    elif os_family == "macos":
        paths = _macos_known_paths()
    else:
        paths = _linux_paths_from_resolver()

    workspace = str(resolve_workspace_path().expanduser())
    safe_remaps: dict[str, str] = {}
    if str(mode).lower() == "safe":
        safe_remaps["desktop"] = workspace

    apps_list = [dict(item) for item in (installed_apps or []) if isinstance(item, dict)]
    installed_app_ids: list[str] = []
    installed_apps_hash = ""
    if apps_list:
        from iuve_connect_agents.shared.app_resolver import (
            compute_installed_apps_hash,
            installed_app_ids_from_entries,
        )

        installed_app_ids = installed_app_ids_from_entries(apps_list)
        installed_apps_hash = compute_installed_apps_hash(apps_list)

    snapshot: dict[str, Any] = {
        "schema_version": DCM_SCHEMA_VERSION,
        "device_id": str(device_id or "").strip(),
        "os_family": os_family,
        "os_version": str(platform.release() or ""),
        "desktop_environment": _detect_desktop_environment(),
        "session": _detect_session(),
        "locale": _detect_locale(),
        "routing_mode": str(mode),
        "paths": {k: str(paths.get(k) or "") for k in _PATH_KEYS},
        "path_aliases": {
            "desktop": "paths.desktop",
            "рабочий стол": "paths.desktop",
            "рабочем столе": "paths.desktop",
            "documents": "paths.documents",
            "документы": "paths.documents",
            "downloads": "paths.downloads",
            "загрузки": "paths.downloads",
            "iuve_workspace": "paths.iuve_workspace",
        },
        "safe_mode_remaps": safe_remaps,
        "apps_indexed": int(apps_indexed or 0),
        "captured_at": datetime.now(timezone.utc).isoformat(),
    }
    if apps_list:
        snapshot["installed_apps"] = apps_list
        snapshot["installed_app_ids"] = installed_app_ids
        snapshot["installed_apps_hash"] = installed_apps_hash
    return snapshot


def extract_device_context_from_snapshot(snapshot: dict[str, Any] | None) -> dict[str, Any] | None:
    """Read embedded DCM or synthesize from legacy capability snapshot folders."""
    if not isinstance(snapshot, dict) or not snapshot:
        return None
    dcm = snapshot.get("device_context")
    if isinstance(dcm, dict) and dcm.get("paths"):
        return dict(dcm)
    folders = snapshot.get("folders")
    if not isinstance(folders, dict):
        return None
    paths = {
        "desktop": str(folders.get("desktop") or ""),
        "documents": str(folders.get("documents") or ""),
        "downloads": str(folders.get("downloads") or ""),
        "iuve_workspace": str(folders.get("workspace") or folders.get("iuve_workspace") or ""),
        "home": str(folders.get("home") or ""),
        "pictures": str(folders.get("pictures") or ""),
        "music": str(folders.get("music") or ""),
        "videos": str(folders.get("videos") or ""),
    }
    if not any(paths.values()):
        return None
    return {
        "schema_version": str(snapshot.get("schema_version") or DCM_SCHEMA_VERSION),
        "device_id": str(snapshot.get("device_id") or ""),
        "os_family": str(snapshot.get("platform") or snapshot.get("os_name") or "").lower(),
        "os_version": str(snapshot.get("os_version") or ""),
        "desktop_environment": str(snapshot.get("desktop_environment") or "unknown"),
        "session": str(snapshot.get("session") or "unknown"),
        "locale": str(snapshot.get("locale") or "unknown"),
        "routing_mode": str(snapshot.get("routing_mode") or "safe"),
        "paths": paths,
        "path_aliases": {},
        "safe_mode_remaps": {},
        "apps_indexed": len(snapshot.get("applications") or []),
        "captured_at": str(snapshot.get("captured_at") or ""),
    }


def resolve_path_from_dcm(
    scope: str,
    *,
    dcm: dict[str, Any] | None = None,
    explicit_desktop: bool = False,
    for_write: bool = True,
) -> tuple[str, str, bool]:
    """Resolve a folder scope using DCM only. Returns (path, policy_hint, remapped)."""
    ctx = dcm if isinstance(dcm, dict) else get_planning_dcm()
    if not ctx:
        return "", "DCM unavailable", False

    paths = ctx.get("paths") if isinstance(ctx.get("paths"), dict) else {}
    key = str(scope or "").strip().lower()
    system_path = str(paths.get(key) or "").strip()
    if not system_path:
        return "", f"DCM missing paths.{key}", False

    mode = str(ctx.get("routing_mode") or "safe").lower()
    remapped = False
    hint = f"DCM paths.{key}: {system_path}"

    if key == "desktop" and for_write:
        safe_remaps = ctx.get("safe_mode_remaps") if isinstance(ctx.get("safe_mode_remaps"), dict) else {}
        remap_target = str(safe_remaps.get("desktop") or "").strip()
        if mode == "safe" and remap_target and not explicit_desktop:
            return remap_target, (
                f"Safe mode: desktop write remapped to {remap_target} "
                f"(system desktop: {system_path})"
            ), True
        if explicit_desktop:
            hint = f"Explicit desktop via DCM: {system_path}"

    return system_path, hint, remapped


def sanitize_dcm_for_cloud_sync(dcm: dict[str, Any]) -> dict[str, Any]:
    """Strip local-only installed_apps details before cloud capability sync."""
    sanitized = dict(dcm)
    installed = sanitized.pop("installed_apps", None)
    if isinstance(installed, list) and installed:
        from iuve_connect_agents.shared.app_resolver import (
            compute_installed_apps_hash,
            installed_app_ids_from_entries,
        )

        sanitized["installed_app_ids"] = installed_app_ids_from_entries(installed)
        sanitized["installed_apps_hash"] = compute_installed_apps_hash(installed)
    return sanitized


def merge_dcm_into_capability_snapshot(snapshot: dict[str, Any]) -> dict[str, Any]:
    """Ensure capability snapshot carries an up-to-date device_context block."""
    merged = dict(snapshot or {})
    apps = merged.get("applications")
    apps_count = len(apps) if isinstance(apps, list) else int(merged.get("apps_indexed") or 0)
    installed_apps: list[dict[str, Any]] | None = None
    if isinstance(merged.get("installed_apps"), list):
        installed_apps = [dict(item) for item in merged["installed_apps"] if isinstance(item, dict)]
    elif isinstance(apps, list) and apps:
        try:
            from iuve_connect_agents.desktop.active.device_capability_scanner import (
                map_inventory_to_installed_apps,
            )

            installed_apps = map_inventory_to_installed_apps(apps)
        except Exception:
            installed_apps = None

    dcm = build_device_context_snapshot(
        device_id=str(merged.get("device_id") or ""),
        trust_state=str(merged.get("trust_state") or ""),
        routing_mode=str(merged.get("routing_mode") or "") or None,
        apps_indexed=apps_count,
        installed_apps=installed_apps,
    )
    merged["device_context"] = dcm
    merged["apps_indexed"] = apps_count
    merged["locale"] = dcm.get("locale")
    merged["session"] = dcm.get("session")
    merged["desktop_environment"] = dcm.get("desktop_environment")
    if installed_apps:
        merged["installed_apps"] = installed_apps
        merged["installed_app_ids"] = dcm.get("installed_app_ids")
        merged["installed_apps_hash"] = dcm.get("installed_apps_hash")
    return merged
