from __future__ import annotations

import json
import sys
from pathlib import Path

sys.path.insert(0, str(Path(__file__).resolve().parents[1]))

from ui.settings_store import Settings, SettingsStore


def _store(tmp_path: Path) -> SettingsStore:
    return SettingsStore(tmp_path / "settings.json")


def test_missing_file_returns_defaults(tmp_path: Path) -> None:
    assert _store(tmp_path).read() == Settings()


def test_round_trip(tmp_path: Path) -> None:
    store = _store(tmp_path)
    settings = Settings(
        auto_close=True,
        refresh_interval_seconds=120,
        warning_threshold_pct=25,
        last_tab="claude",
    )
    store.write(settings)
    assert store.read() == settings


def test_write_creates_parent_directory(tmp_path: Path) -> None:
    store = SettingsStore(tmp_path / "nested" / "dir" / "settings.json")
    store.write(Settings(last_tab="grok"))
    assert store.read().last_tab == "grok"


def test_corrupt_json_returns_defaults(tmp_path: Path) -> None:
    store = _store(tmp_path)
    store.path.write_text("{not json", encoding="utf-8")
    assert store.read() == Settings()


def test_non_object_json_returns_defaults(tmp_path: Path) -> None:
    store = _store(tmp_path)
    store.path.write_text("[1, 2]", encoding="utf-8")
    assert store.read() == Settings()


def test_partial_file_fills_defaults(tmp_path: Path) -> None:
    store = _store(tmp_path)
    store.path.write_text(json.dumps({"warning_threshold_pct": 30}), encoding="utf-8")
    settings = store.read()
    assert settings.warning_threshold_pct == 30
    assert settings.auto_close is False
    assert settings.refresh_interval_seconds == 60
    assert settings.last_tab == ""
    assert settings.theme == "system"


def test_unknown_keys_ignored(tmp_path: Path) -> None:
    store = _store(tmp_path)
    store.path.write_text(
        json.dumps({"auto_close": True, "bogus": 1, "future_key": "x"}),
        encoding="utf-8",
    )
    assert store.read() == Settings(auto_close=True)


def test_theme_round_trip_and_invalid_falls_back(tmp_path: Path) -> None:
    store = _store(tmp_path)
    store.write(Settings(theme="dark"))
    assert store.read().theme == "dark"
    store.path.write_text(json.dumps({"theme": "neon"}), encoding="utf-8")
    assert store.read().theme == "system"
    store.path.write_text(json.dumps({"theme": 3}), encoding="utf-8")
    assert store.read().theme == "system"


def test_out_of_range_numbers_clamped(tmp_path: Path) -> None:
    store = _store(tmp_path)
    store.path.write_text(
        json.dumps(
            {
                "refresh_interval_seconds": 5,
                "warning_threshold_pct": 99,
            }
        ),
        encoding="utf-8",
    )
    settings = store.read()
    assert settings.refresh_interval_seconds == 30
    assert settings.warning_threshold_pct == 50

    store.path.write_text(
        json.dumps(
            {
                "refresh_interval_seconds": 999_999,
                "warning_threshold_pct": 0,
            }
        ),
        encoding="utf-8",
    )
    settings = store.read()
    assert settings.refresh_interval_seconds == 3600
    assert settings.warning_threshold_pct == 1


def test_wrong_types_fall_back_to_defaults(tmp_path: Path) -> None:
    store = _store(tmp_path)
    store.path.write_text(
        json.dumps(
            {
                "auto_close": "yes",
                "refresh_interval_seconds": "120",
                "warning_threshold_pct": True,
                "last_tab": 3,
            }
        ),
        encoding="utf-8",
    )
    assert store.read() == Settings()


def test_atomic_write_leaves_valid_file_and_no_temp_files(tmp_path: Path) -> None:
    store = _store(tmp_path)
    store.write(Settings())
    store.write(Settings(auto_close=True, last_tab="codex"))
    payload = json.loads(store.path.read_text(encoding="utf-8"))
    assert payload == {
        "auto_close": True,
        "refresh_interval_seconds": 60,
        "warning_threshold_pct": 15,
        "last_tab": "codex",
        "theme": "system",
    }
    assert [entry.name for entry in tmp_path.iterdir()] == ["settings.json"]
