import sys
from pathlib import Path
from tempfile import TemporaryDirectory
from types import SimpleNamespace
import string

from helpers import create_vault, TEST_SEED, TEST_PASSWORD

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

from seedpass.core.entry_management import EntryManager
from seedpass.core.backup import BackupManager
from seedpass.core.manager import PasswordManager, EncryptionMode
from seedpass.core.config_manager import ConfigManager
from seedpass.core.password_generation import PasswordGenerator, PasswordPolicy


class DummyEnc:
    def derive_seed_from_mnemonic(self, mnemonic):
        return b"\x00" * 32


class DummyBIP85:
    def derive_entropy(self, index: int, bytes_len: int, app_no: int = 32) -> bytes:
        return bytes((index + i) % 256 for i in range(bytes_len))


def make_manager(tmp_path: Path) -> PasswordManager:
    vault, enc_mgr = create_vault(tmp_path, TEST_SEED, TEST_PASSWORD)
    cfg_mgr = ConfigManager(vault, tmp_path)
    backup_mgr = BackupManager(tmp_path, cfg_mgr)
    entry_mgr = EntryManager(vault, backup_mgr)

    pg = PasswordGenerator.__new__(PasswordGenerator)
    pg.encryption_manager = DummyEnc()
    pg.bip85 = DummyBIP85()
    pg.policy = PasswordPolicy(
        min_uppercase=0, min_lowercase=0, min_digits=1, min_special=0
    )

    pm = PasswordManager.__new__(PasswordManager)
    pm.encryption_mode = EncryptionMode.SEED_ONLY
    pm.password_generator = pg
    pm.entry_manager = entry_mgr
    pm.parent_seed = TEST_SEED
    pm.vault = vault
    pm.backup_manager = backup_mgr
    pm.nostr_client = SimpleNamespace()
    pm.fingerprint_dir = tmp_path
    pm.secret_mode_enabled = False
    return pm


def test_entry_policy_override_changes_password():
    with TemporaryDirectory() as tmpdir:
        tmp_path = Path(tmpdir)
        pm = make_manager(tmp_path)
        idx = pm.entry_manager.add_entry(
            "site",
            16,
            min_digits=5,
            include_special_chars=False,
        )
        entry = pm.entry_manager.retrieve_entry(idx)
        pw = pm._generate_password_for_entry(entry, idx)
        assert sum(c.isdigit() for c in pw) >= 5
        assert not any(c in string.punctuation for c in pw)
