"""Persistent node configuration — stored in ~/.config/meshnet/config.json."""

from __future__ import annotations

import json
import os
import stat
from pathlib import Path

_DEFAULT_CONFIG_DIR = Path.home() / ".config" / "meshnet"
_DEFAULT_CONFIG_FILE = _DEFAULT_CONFIG_DIR / "config.json"
# MESHNET_DOWNLOAD_DIR overrides the model store for every node on this
# machine (all CLI flows fall back to this default; --download-dir still wins).
_DEFAULT_DOWNLOAD_DIR = Path(
    os.environ.get("MESHNET_DOWNLOAD_DIR", str(Path.home() / ".meshnet" / "models"))
)
_DEFAULT_TRACKER_URL = os.environ.get("MESHNET_TRACKER_URL", "http://localhost:8080")
_DEFAULT_WALLET_PATH = str(Path.home() / ".config" / "meshnet" / "wallet.json")
_DEFAULT_QUANTIZATION = "auto"
_DEFAULT_MODEL = os.environ.get("MESHNET_MODEL_ID") or os.environ.get("MESHNET_MODEL", "")
_DEFAULT_MODEL_HF_REPO = _DEFAULT_MODEL if "/" in _DEFAULT_MODEL else ""
_DEFAULT_MODEL_NAME = _DEFAULT_MODEL.split("/")[-1] if "/" in _DEFAULT_MODEL else _DEFAULT_MODEL

DEFAULTS = {
    "model_hf_repo": _DEFAULT_MODEL_HF_REPO,
    "model_name": _DEFAULT_MODEL_NAME,
    "quantization": _DEFAULT_QUANTIZATION,
    "download_dir": str(_DEFAULT_DOWNLOAD_DIR),
    "tracker_url": _DEFAULT_TRACKER_URL,
    "wallet_path": _DEFAULT_WALLET_PATH,
    "shard_start": None,
    "shard_end": None,
    "port": 7000,
    "host": "0.0.0.0",
    "debug": False,
}


def config_path(override: Path | None = None) -> Path:
    return override or _DEFAULT_CONFIG_FILE


def load_config(path: Path | None = None) -> dict | None:
    """Return parsed config dict, or None if no config file exists."""
    p = config_path(path)
    if not p.exists():
        return None
    try:
        cfg = json.loads(p.read_text())
        if not isinstance(cfg, dict):
            return None
        return cfg
    except (json.JSONDecodeError, OSError):
        return None


def save_config(cfg: dict, path: Path | None = None) -> None:
    """Write config to disk with restricted permissions (0o600)."""
    p = config_path(path)
    p.parent.mkdir(parents=True, exist_ok=True)
    p.write_text(json.dumps(cfg, indent=2))
    try:
        os.chmod(p, stat.S_IRUSR | stat.S_IWUSR)
    except OSError:
        pass  # Windows / some filesystems don't support chmod


def delete_config(path: Path | None = None) -> None:
    p = config_path(path)
    if p.exists():
        p.unlink()


def merge_cli_overrides(cfg: dict, **cli_kwargs) -> dict:
    """Return a copy of cfg with any non-None CLI values applied on top."""
    result = dict(cfg)
    for key, val in cli_kwargs.items():
        if val is not None:
            result[key] = val
    return result
