"""Tests for MLD client credential config storage."""

import json
import stat
from pathlib import Path

import pytest

from mld_sdk.client._config import (
    _config_dir,
    get_default_host,
    get_stored_token,
    get_stored_username,
    load_config,
    remove_token,
    save_config,
    set_default_host,
    store_token,
)


@pytest.fixture(autouse=True)
def _isolated_config(tmp_path: Path, monkeypatch: pytest.MonkeyPatch):
    """Redirect config dir to a temp directory for all tests."""
    monkeypatch.setenv("XDG_CONFIG_HOME", str(tmp_path))


class TestLoadSaveConfig:
    def test_load_returns_empty_when_no_file(self):
        config = load_config()
        assert config == {"version": 1, "default_host": None, "hosts": {}}

    def test_save_and_load_round_trip(self):
        config = {"version": 1, "default_host": "http://localhost", "hosts": {}}
        save_config(config)
        assert load_config() == config

    def test_save_sets_restrictive_permissions(self):
        save_config({"version": 1, "default_host": None, "hosts": {}})
        path = _config_dir() / "credentials.json"
        mode = path.stat().st_mode
        assert mode & stat.S_IRUSR  # owner can read
        assert mode & stat.S_IWUSR  # owner can write
        assert not mode & stat.S_IRGRP  # group cannot read
        assert not mode & stat.S_IROTH  # others cannot read

    def test_load_handles_corrupt_json(self):
        path = _config_dir() / "credentials.json"
        path.parent.mkdir(parents=True, exist_ok=True)
        path.write_text("not json{{{", encoding="utf-8")
        config = load_config()
        assert config["hosts"] == {}

    def test_load_handles_missing_hosts_key(self):
        path = _config_dir() / "credentials.json"
        path.parent.mkdir(parents=True, exist_ok=True)
        path.write_text(json.dumps({"version": 1}), encoding="utf-8")
        config = load_config()
        assert config["hosts"] == {}


class TestTokenStorage:
    def test_store_and_retrieve_token(self):
        store_token("http://localhost:8001", "tok123", "admin", "2026-04-01T00:00:00Z")
        assert get_stored_token("http://localhost:8001") == "tok123"

    def test_trailing_slash_normalized(self):
        store_token("http://localhost:8001/", "tok123", "admin")
        assert get_stored_token("http://localhost:8001") == "tok123"
        assert get_stored_token("http://localhost:8001/") == "tok123"

    def test_get_stored_token_returns_none_for_unknown_host(self):
        assert get_stored_token("http://unknown:9999") is None

    def test_store_sets_default_host(self):
        store_token("http://my-server.com", "tok", "user")
        assert get_default_host() == "http://my-server.com"

    def test_remove_token_clears_entry(self):
        store_token("http://localhost:8001", "tok", "admin")
        remove_token("http://localhost:8001")
        assert get_stored_token("http://localhost:8001") is None

    def test_remove_token_clears_default_host(self):
        store_token("http://localhost:8001", "tok", "admin")
        remove_token("http://localhost:8001")
        assert get_default_host() is None

    def test_remove_preserves_other_hosts(self):
        store_token("http://host-a", "tok-a", "user-a")
        store_token("http://host-b", "tok-b", "user-b")
        remove_token("http://host-a")
        assert get_stored_token("http://host-b") == "tok-b"

    def test_get_stored_username(self):
        store_token("http://localhost:8001", "tok", "estrella")
        assert get_stored_username("http://localhost:8001") == "estrella"

    def test_get_stored_username_returns_none_for_unknown(self):
        assert get_stored_username("http://unknown:9999") is None


class TestDefaultHost:
    def test_set_and_get_default_host(self):
        set_default_host("http://my-lab.com")
        assert get_default_host() == "http://my-lab.com"

    def test_default_host_strips_trailing_slash(self):
        set_default_host("http://my-lab.com/")
        assert get_default_host() == "http://my-lab.com"

    def test_no_default_host_initially(self):
        assert get_default_host() is None
