import bcrypt
from pathlib import Path
from tempfile import TemporaryDirectory
import pytest
from helpers import create_vault, TEST_SEED, TEST_PASSWORD
import sys

sys.path.append(str(Path(__file__).resolve().parents[1]))

from password_manager.config_manager import ConfigManager
from password_manager.vault import Vault
from nostr.client import DEFAULT_RELAYS


def test_config_defaults_and_round_trip():
    with TemporaryDirectory() as tmpdir:
        vault, enc_mgr = create_vault(Path(tmpdir), TEST_SEED, TEST_PASSWORD)
        cfg_mgr = ConfigManager(vault, Path(tmpdir))

        cfg = cfg_mgr.load_config(require_pin=False)
        assert cfg["relays"] == list(DEFAULT_RELAYS)
        assert cfg["pin_hash"] == ""
        assert cfg["password_hash"] == ""

        cfg_mgr.set_pin("1234")
        cfg_mgr.set_relays(["wss://example.com"], require_pin=False)

        cfg2 = cfg_mgr.load_config(require_pin=False)
        assert cfg2["relays"] == ["wss://example.com"]
        assert bcrypt.checkpw(b"1234", cfg2["pin_hash"].encode())


def test_pin_verification_and_change():
    with TemporaryDirectory() as tmpdir:
        vault, enc_mgr = create_vault(Path(tmpdir), TEST_SEED, TEST_PASSWORD)
        cfg_mgr = ConfigManager(vault, Path(tmpdir))

        cfg_mgr.set_pin("1234")
        assert cfg_mgr.verify_pin("1234")
        assert not cfg_mgr.verify_pin("0000")
        assert cfg_mgr.change_pin("1234", "5678")
        assert cfg_mgr.verify_pin("5678")


import json


def test_config_file_encrypted_after_save():
    with TemporaryDirectory() as tmpdir:
        vault, enc_mgr = create_vault(Path(tmpdir), TEST_SEED, TEST_PASSWORD)
        cfg_mgr = ConfigManager(vault, Path(tmpdir))

        data = {"relays": ["wss://r"], "pin_hash": ""}
        cfg_mgr.save_config(data)

        file_path = Path(tmpdir) / cfg_mgr.CONFIG_FILENAME
        raw = file_path.read_bytes()
        assert raw != json.dumps(data).encode()

        loaded = cfg_mgr.load_config(require_pin=False)
        assert loaded["relays"] == data["relays"]
        assert loaded["pin_hash"] == data["pin_hash"]
        assert loaded["password_hash"] == ""


def test_set_relays_persists_changes():
    with TemporaryDirectory() as tmpdir:
        vault, enc_mgr = create_vault(Path(tmpdir), TEST_SEED, TEST_PASSWORD)
        cfg_mgr = ConfigManager(vault, Path(tmpdir))
        cfg_mgr.set_relays(["wss://custom"], require_pin=False)
        cfg = cfg_mgr.load_config(require_pin=False)
        assert cfg["relays"] == ["wss://custom"]


def test_set_relays_requires_at_least_one():
    with TemporaryDirectory() as tmpdir:
        vault, enc_mgr = create_vault(Path(tmpdir), TEST_SEED, TEST_PASSWORD)
        cfg_mgr = ConfigManager(vault, Path(tmpdir))
        with pytest.raises(ValueError):
            cfg_mgr.set_relays([], require_pin=False)


def test_password_hash_migrates_from_file(tmp_path):
    vault, enc_mgr = create_vault(tmp_path, TEST_SEED, TEST_PASSWORD)
    cfg_mgr = ConfigManager(vault, tmp_path)

    # save legacy config without password_hash
    legacy_cfg = {"relays": ["wss://r"], "pin_hash": ""}
    cfg_mgr.save_config(legacy_cfg)

    hashed = bcrypt.hashpw(b"pw", bcrypt.gensalt())
    (tmp_path / "hashed_password.enc").write_bytes(hashed)

    cfg = cfg_mgr.load_config(require_pin=False)
    assert cfg["password_hash"] == hashed.decode()
    # subsequent loads should read from config
    (tmp_path / "hashed_password.enc").unlink()
    cfg2 = cfg_mgr.load_config(require_pin=False)
    assert cfg2["password_hash"] == hashed.decode()
