"""Persist UI preferences in the data dir (survives desktop port changes)."""

from __future__ import annotations

import json
import threading
from pathlib import Path
from typing import Any, Dict, Optional

from . import config

_lock = threading.RLock()
SETTINGS_PATH = config.DATA_DIR / "user_settings.json"

_DEFAULT: Dict[str, Any] = {
    "theme": "dark",
    "lang": None,
}


def _read() -> dict:
    if not SETTINGS_PATH.exists():
        return dict(_DEFAULT)
    try:
        with SETTINGS_PATH.open(encoding="utf-8") as f:
            data = json.load(f)
        if not isinstance(data, dict):
            return dict(_DEFAULT)
        out = dict(_DEFAULT)
        if data.get("theme") in ("light", "dark"):
            out["theme"] = data["theme"]
        if isinstance(data.get("lang"), str) and data["lang"].strip():
            out["lang"] = data["lang"].strip()
        return out
    except (OSError, json.JSONDecodeError):
        return dict(_DEFAULT)


def _write(data: dict) -> None:
    SETTINGS_PATH.parent.mkdir(parents=True, exist_ok=True)
    tmp = SETTINGS_PATH.with_suffix(".json.tmp")
    with tmp.open("w", encoding="utf-8") as f:
        json.dump(data, f, ensure_ascii=False, indent=2)
    tmp.replace(SETTINGS_PATH)


def load() -> dict:
    with _lock:
        return _read()


def save(*, theme: Optional[str] = None, lang: Optional[str] = None) -> dict:
    with _lock:
        data = _read()
        if theme in ("light", "dark"):
            data["theme"] = theme
        if lang is not None:
            cleaned = lang.strip()
            data["lang"] = cleaned or None
        _write(data)
        return dict(data)
