"""Tests for brynq.vault — credential storage with encryption."""

import json
import pytest
from pathlib import Path


@pytest.fixture(autouse=True)
def _isolate_vault(tmp_path, monkeypatch):
    """Redirect vault to temp directory."""
    vault_file = tmp_path / "vault.json"
    monkeypatch.setattr("brynq.vault.VAULT_FILE", vault_file)


class TestVaultStoreAndGet:
    def test_store_and_retrieve(self):
        from brynq.vault import vault_store, vault_get
        vault_store("openai", "test-key-12345")
        assert vault_get("openai") == "test-key-12345"

    def test_case_insensitive(self):
        from brynq.vault import vault_store, vault_get
        vault_store("OpenAI", "mykey")
        assert vault_get("openai") == "mykey"
        assert vault_get("OPENAI") == "mykey"

    def test_overwrite_key(self):
        from brynq.vault import vault_store, vault_get
        vault_store("ollama", "key1")
        vault_store("ollama", "key2")
        assert vault_get("ollama") == "key2"

    def test_get_nonexistent_returns_none(self):
        from brynq.vault import vault_get
        assert vault_get("nonexistent") is None

    def test_multiple_platforms(self):
        from brynq.vault import vault_store, vault_get
        vault_store("openai", "oai-key")
        vault_store("anthropic", "ant-key")
        vault_store("google", "goo-key")
        assert vault_get("openai") == "oai-key"
        assert vault_get("anthropic") == "ant-key"
        assert vault_get("google") == "goo-key"


class TestVaultList:
    def test_empty_vault(self):
        from brynq.vault import vault_list
        assert vault_list() == []

    def test_lists_stored_platforms(self):
        from brynq.vault import vault_store, vault_list
        vault_store("openai", "k1")
        vault_store("anthropic", "k2")
        platforms = vault_list()
        assert sorted(platforms) == ["anthropic", "openai"]


class TestVaultDelete:
    def test_delete_existing(self):
        from brynq.vault import vault_store, vault_delete, vault_get
        vault_store("openai", "key")
        assert vault_delete("openai") is True
        assert vault_get("openai") is None

    def test_delete_nonexistent(self):
        from brynq.vault import vault_delete
        assert vault_delete("nonexistent") is False

    def test_delete_preserves_others(self):
        from brynq.vault import vault_store, vault_delete, vault_get
        vault_store("openai", "k1")
        vault_store("anthropic", "k2")
        vault_delete("openai")
        assert vault_get("anthropic") == "k2"


class TestEncryption:
    def test_stored_value_is_encrypted(self):
        from brynq.vault import vault_store, VAULT_FILE
        vault_store("openai", "plaintext-secret")
        data = json.loads(VAULT_FILE.read_text("utf-8"))
        stored = data["keys"]["openai"]
        assert stored != "plaintext-secret"

    def test_different_ciphertext_each_time(self):
        from brynq.vault import _encrypt
        enc1 = _encrypt("same-input")
        enc2 = _encrypt("same-input")
        assert enc1 != enc2  # Random IV means different output

    def test_roundtrip_special_characters(self):
        from brynq.vault import vault_store, vault_get
        special = "key-with-spëcial/chars+and=symbols!@#$%"
        vault_store("test", special)
        assert vault_get("test") == special

    def test_roundtrip_long_key(self):
        from brynq.vault import vault_store, vault_get
        long_key = "x" * 500
        vault_store("test", long_key)
        assert vault_get("test") == long_key

    def test_roundtrip_empty_string_returns_none(self):
        from brynq.vault import vault_store, vault_get
        # Empty/falsy keys are treated as "no key" by design
        vault_store("test", "")
        assert vault_get("test") is None


class TestLegacyCompat:
    def test_reads_legacy_xor_format(self):
        import base64, hashlib, socket, getpass
        from brynq.vault import vault_get, VAULT_FILE

        # Simulate old XOR encryption
        hostname = socket.gethostname()
        username = getpass.getuser()
        key = hashlib.sha256(f"{hostname}:{username}:brynq-salt".encode()).digest()
        plaintext = "legacy-api-key"
        pt_bytes = plaintext.encode("utf-8")
        encrypted = bytearray(b ^ key[i % len(key)] for i, b in enumerate(pt_bytes))
        legacy_enc = base64.b64encode(encrypted).decode("utf-8")

        # Write legacy format to vault
        VAULT_FILE.parent.mkdir(parents=True, exist_ok=True)
        VAULT_FILE.write_text(json.dumps({"keys": {"old_platform": legacy_enc}}, indent=2))

        assert vault_get("old_platform") == "legacy-api-key"
