"""Tests for the encrypted vault and config."""

from unittest.mock import patch

from clawdflare.lib.vault import (
    encrypt_token,
    _decrypt_token,
    save_read_token,
    get_read_token,
    list_accounts,
    set_active_account,
    get_active_account,
)


def test_encrypt_decrypt_roundtrip(tmp_path):
    """Encrypting and decrypting with the same PIN returns the original token."""
    vault_file = tmp_path / "vault.enc"

    with patch("clawdflare.lib.vault._vault_file", return_value=vault_file), \
         patch("clawdflare.lib.vault.VAULT_DIR", tmp_path):
        token = "cf_test_token_abc123"
        pin = "mypin1234"

        encrypt_token(token, pin)
        assert vault_file.exists()

        recovered = _decrypt_token(pin)
        assert recovered == token


def test_wrong_pin_fails(tmp_path):
    """Decrypting with the wrong PIN raises an error."""
    vault_file = tmp_path / "vault.enc"

    with patch("clawdflare.lib.vault._vault_file", return_value=vault_file), \
         patch("clawdflare.lib.vault.VAULT_DIR", tmp_path):
        encrypt_token("cf_test_token", "correctpin")

        try:
            _decrypt_token("wrongpin")
            assert False, "Should have raised RuntimeError"
        except RuntimeError as e:
            assert "Wrong PIN" in str(e)


def test_vault_file_permissions(tmp_path):
    """Vault file should be created with 600 permissions."""
    vault_file = tmp_path / "vault.enc"

    with patch("clawdflare.lib.vault._vault_file", return_value=vault_file), \
         patch("clawdflare.lib.vault.VAULT_DIR", tmp_path):
        encrypt_token("cf_test_token", "pin123")
        mode = oct(vault_file.stat().st_mode)[-3:]
        assert mode == "600"


def test_multi_account_config(tmp_path):
    """Multiple accounts can store separate read tokens."""
    config_file = tmp_path / "config.json"

    with patch("clawdflare.lib.vault.CONFIG_FILE", config_file), \
         patch("clawdflare.lib.vault.VAULT_DIR", tmp_path):
        save_read_token("token_personal", "personal", token_name="cf-read-personal")
        save_read_token("token_work", "work", token_name="cf-read-work")

        assert get_read_token("personal") == "token_personal"
        assert get_read_token("work") == "token_work"

        # First account becomes active by default
        assert get_active_account() == "personal"


def test_switch_active_account(tmp_path):
    """Switching active account changes which token is returned by default."""
    config_file = tmp_path / "config.json"

    with patch("clawdflare.lib.vault.CONFIG_FILE", config_file), \
         patch("clawdflare.lib.vault.VAULT_DIR", tmp_path):
        save_read_token("token_a", "alpha")
        save_read_token("token_b", "beta")

        assert get_read_token() == "token_a"  # alpha is active (first added)

        set_active_account("beta")
        assert get_read_token() == "token_b"


def test_list_accounts_with_token_names(tmp_path):
    """list_accounts returns token names for rotation reference."""
    config_file = tmp_path / "config.json"
    vault_file = tmp_path / "test.vault.enc"

    with patch("clawdflare.lib.vault.CONFIG_FILE", config_file), \
         patch("clawdflare.lib.vault.VAULT_DIR", tmp_path), \
         patch("clawdflare.lib.vault._vault_file", return_value=vault_file):
        save_read_token("tok", "myacct", token_name="clawdflare-read")
        encrypt_token("write_tok", "pin123", "myacct", token_name="clawdflare-write")

        accts = list_accounts()
        assert len(accts) == 1
        assert accts[0]["name"] == "myacct"
        assert accts[0]["read_token_name"] == "clawdflare-read"
        assert accts[0]["write_token_name"] == "clawdflare-write"
        assert accts[0]["has_read_token"] is True
        assert accts[0]["has_write_vault"] is True


def test_multi_account_vaults(tmp_path):
    """Each account gets its own encrypted vault file."""
    config_file = tmp_path / "config.json"

    with patch("clawdflare.lib.vault.CONFIG_FILE", config_file), \
         patch("clawdflare.lib.vault.VAULT_DIR", tmp_path):
        encrypt_token("personal_write", "pin_p", "personal")
        encrypt_token("work_write", "pin_w", "work")

        # Each has its own vault file
        assert (tmp_path / "personal.vault.enc").exists()
        assert (tmp_path / "work.vault.enc").exists()

        # Each decrypts with its own PIN
        recovered_p = _decrypt_token("pin_p", "personal")
        recovered_w = _decrypt_token("pin_w", "work")
        assert recovered_p == "personal_write"
        assert recovered_w == "work_write"

        # Wrong PIN on wrong account fails
        try:
            _decrypt_token("pin_p", "work")
            assert False, "Should have raised"
        except RuntimeError:
            pass
