from __future__ import annotations

import os
import tomllib
from dataclasses import dataclass, field
from pathlib import Path


DEFAULT_PROTECT = {
    "systemd", "systemd-oomd", "pipewire", "pipewire-pulse", "wireplumber",
    "dbus-daemon", "dbus-broker", "gnome-shell", "plasmashell", "kwin_x11",
    "kwin_wayland", "mutter", "Xorg", "Xwayland", "gnome-session", "xfwm4",
    "xfce4-session", "xfsettingsd", "lightdm", "sddm", "gdm",
    "gnome-keyring-daemon", "polkitd", "bash", "notify-send", "python3",
}

DEFAULT_BUILD_ALLOWLIST = [
    "tsc", "vite", "esbuild", "rollup", "webpack", "turbo", "pnpm", "npm",
    "yarn", "node", "cargo", "rustc", "cc", "clang", "gcc", "ld", "make",
    "ninja", "go", "bun",
]

# Tailscale CGNAT + ULA — Peer API and tailnet services bind here by design.
DEFAULT_TRUSTED_HOST_CIDRS = ["100.64.0.0/10", "fd7a:115c:a1e0::/48"]


@dataclass
class Config:
    tmp_stale_hours: int = 72
    protect: set[str] = field(default_factory=lambda: set(DEFAULT_PROTECT))
    build_allowlist: list[str] = field(default_factory=lambda: list(DEFAULT_BUILD_ALLOWLIST))
    watched_paths: list[str] = field(default_factory=lambda: [
        "~/.ssh", "/var/spool/cron/crontabs", "~/.config/systemd/user", "/etc/systemd/system",
    ])
    dev_port_allowlist: list[str] = field(default_factory=lambda: ["3000-9999", "5173", "4321", "6006"])
    trusted_host_cidrs: list[str] = field(default_factory=lambda: list(DEFAULT_TRUSTED_HOST_CIDRS))
    cooldowns: dict[str, int] = field(default_factory=lambda: {"default": 300, "fswatch": 120, "ports": 600})
    thresholds: dict[str, float] = field(default_factory=lambda: {
        "mem_eta_warn": 360, "mem_eta_critical": 90, "mem_floor_pct": 8,
        "tmpfs_warn_pct": 85, "tmpfs_critical_pct": 95,
    })
    state_path: Path = Path(os.environ.get("XDG_STATE_HOME", "~/.local/state")).expanduser() / "system-monitor" / "agent-guard.json"
    socket_path: Path = Path(os.environ.get("XDG_RUNTIME_DIR", "/tmp")).expanduser() / "system-monitor" / "agent-guard.sock"


def load_config(path: str | os.PathLike[str] | None = None) -> Config:
    cfg = Config()
    p = Path(path or os.environ.get("AGENT_GUARD_CONFIG", "/etc/system-monitor/agent-guard.toml"))
    if not p.exists():
        local = Path(__file__).resolve().parents[3] / "config" / "agent-guard.toml"
        p = local if local.exists() else p
    if p.exists():
        data = tomllib.loads(p.read_text())
        for key in ("tmp_stale_hours", "watched_paths", "dev_port_allowlist", "trusted_host_cidrs", "build_allowlist"):
            if key in data:
                setattr(cfg, key, data[key])
        if "protect" in data:
            cfg.protect = set(data["protect"])
        if "cooldowns" in data:
            cfg.cooldowns.update({str(k): int(v) for k, v in data["cooldowns"].items()})
        if "thresholds" in data:
            cfg.thresholds.update({str(k): float(v) for k, v in data["thresholds"].items()})
        if "state_path" in data:
            cfg.state_path = Path(data["state_path"]).expanduser()
        if "socket_path" in data:
            cfg.socket_path = Path(data["socket_path"]).expanduser()
    return cfg
