from __future__ import annotations

import json
import os
import tempfile
from dataclasses import dataclass
from pathlib import Path

from ui.theme import ThemePreference, normalize_theme_preference

_REFRESH_MIN_S = 30
_REFRESH_MAX_S = 3600
_THRESHOLD_MIN_PCT = 1
_THRESHOLD_MAX_PCT = 50


@dataclass(frozen=True)
class Settings:
    auto_close: bool = False
    refresh_interval_seconds: int = 60
    warning_threshold_pct: int = 15
    last_tab: str = ""
    theme: ThemePreference = "system"


class SettingsStore:
    def __init__(self, path: Path) -> None:
        self.path = path

    def read(self) -> Settings:
        try:
            raw = json.loads(self.path.read_text(encoding="utf-8"))
        except (OSError, ValueError):
            return Settings()
        if not isinstance(raw, dict):
            return Settings()
        defaults = Settings()
        return Settings(
            auto_close=_read_bool(raw.get("auto_close"), defaults.auto_close),
            refresh_interval_seconds=_read_int(
                raw.get("refresh_interval_seconds"),
                defaults.refresh_interval_seconds,
                _REFRESH_MIN_S,
                _REFRESH_MAX_S,
            ),
            warning_threshold_pct=_read_int(
                raw.get("warning_threshold_pct"),
                defaults.warning_threshold_pct,
                _THRESHOLD_MIN_PCT,
                _THRESHOLD_MAX_PCT,
            ),
            last_tab=_read_str(raw.get("last_tab"), defaults.last_tab),
            theme=normalize_theme_preference(raw.get("theme"), defaults.theme),
        )

    def write(self, settings: Settings) -> None:
        self.path.parent.mkdir(parents=True, exist_ok=True)
        payload = {
            "auto_close": settings.auto_close,
            "refresh_interval_seconds": settings.refresh_interval_seconds,
            "warning_threshold_pct": settings.warning_threshold_pct,
            "last_tab": settings.last_tab,
            "theme": settings.theme,
        }

        with tempfile.NamedTemporaryFile(
            "w",
            encoding="utf-8",
            dir=self.path.parent,
            delete=False,
        ) as temp_file:
            json.dump(payload, temp_file, sort_keys=True)
            temp_file.flush()
            os.fsync(temp_file.fileno())
            temp_path = Path(temp_file.name)

        temp_path.replace(self.path)


def _read_bool(value: object, default: bool) -> bool:
    if isinstance(value, bool):
        return value
    return default


def _read_int(value: object, default: int, minimum: int, maximum: int) -> int:
    if isinstance(value, bool) or not isinstance(value, int):
        return default
    return max(minimum, min(maximum, value))


def _read_str(value: object, default: str) -> str:
    if isinstance(value, str):
        return value
    return default
