import os
from pathlib import Path

from hypothesis import given, strategies as st, settings, HealthCheck
from mnemonic import Mnemonic

from utils.key_derivation import (
    derive_key_from_password,
    derive_key_from_password_argon2,
    derive_index_key,
)
from seedpass.core.encryption import EncryptionManager


cfg_values = st.one_of(
    st.integers(min_value=0, max_value=100),
    st.text(min_size=0, max_size=20),
    st.booleans(),
)


@given(
    password=st.text(min_size=8, max_size=32),
    seed_bytes=st.binary(min_size=16, max_size=16),
    config=st.dictionaries(st.text(min_size=1, max_size=10), cfg_values, max_size=5),
    mode=st.sampled_from(["pbkdf2", "argon2"]),
)
@settings(
    deadline=None,
    max_examples=20,
    suppress_health_check=[HealthCheck.function_scoped_fixture],
)
def test_fuzz_key_round_trip(password, seed_bytes, config, mode, tmp_path: Path):
    """Ensure EncryptionManager round-trips arbitrary data."""
    seed_phrase = Mnemonic("english").to_mnemonic(seed_bytes)
    if mode == "argon2":
        key = derive_key_from_password_argon2(
            password, time_cost=1, memory_cost=8, parallelism=1
        )
    else:
        key = derive_key_from_password(password, iterations=1)

    enc_mgr = EncryptionManager(key, tmp_path)

    # Parent seed round trip
    enc_mgr.encrypt_parent_seed(seed_phrase)
    assert enc_mgr.decrypt_parent_seed() == seed_phrase

    # JSON data round trip
    enc_mgr.save_json_data(config, Path("config.enc"))
    loaded = enc_mgr.load_json_data(Path("config.enc"))
    assert loaded == config

    # Binary data round trip
    blob = os.urandom(32)
    enc_mgr.encrypt_and_save_file(blob, Path("blob.enc"))
    assert enc_mgr.decrypt_file(Path("blob.enc")) == blob

    # Index key derived from seed also decrypts
    index_key = derive_index_key(seed_phrase)
    idx_mgr = EncryptionManager(index_key, tmp_path)
    idx_mgr.save_json_data(config)
    assert idx_mgr.load_json_data() == config
