import importlib.util
import subprocess
import sys
import tempfile
from pathlib import Path
import unittest

ROOT = Path(__file__).resolve().parents[1]
SCRIPT = ROOT / 'ci' / 'check_base_v3_release_scope.py'
SPEC = importlib.util.spec_from_file_location('base_scope', SCRIPT)
assert SPEC and SPEC.loader
MODULE = importlib.util.module_from_spec(SPEC)
SPEC.loader.exec_module(MODULE)

class BaseV3ReleaseScopeTest(unittest.TestCase):
    def test_scope_allows_only_explicit_base_paths(self):
        self.assertEqual(MODULE.scope_errors(['v3-src/contracts/bonds/PartnershipBondV3Safe.sol', 'pr10/partner-package/docs/ACCOUNTABILITY_TYPED_ENFORCEMENT_V1.md', 'pr11/base-sepolia-rehearsal/scripts/validate_v3_candidate_manifest.py', 'repos/vaultfire-sdk/dist/baseSepoliaV3Rehearsal.js']), [])

    def test_scope_rejects_solana_unrelated_and_deleted_paths(self):
        errors = MODULE.scope_errors(['repos/vaultfire-solana/programs/vaultfire/src/lib.rs', 'repos/vaultfire-avalanche/README.md', 'repos/vaultfire-solana/deleted.txt'])
        self.assertGreaterEqual(sum('Solana' in error for error in errors), 2)
        self.assertTrue(any('outside explicit allowlist' in error for error in errors))

    def test_git_invocation_includes_deletion_and_authoritative_gate_requires_clean_scope(self):
        with tempfile.TemporaryDirectory() as directory:
            repo = Path(directory)
            subprocess.run(['git', 'init', '-q', str(repo)], check=True)
            subprocess.run(['git', '-C', str(repo), 'config', 'user.email', 'test@example.invalid'], check=True)
            subprocess.run(['git', '-C', str(repo), 'config', 'user.name', 'test'], check=True)
            bad = repo / 'repos/vaultfire-solana/delete-me'; bad.parent.mkdir(parents=True); bad.write_text('x')
            subprocess.run(['git', '-C', str(repo), 'add', '.'], check=True); subprocess.run(['git', '-C', str(repo), 'commit', '-qm', 'base'], check=True)
            base = subprocess.check_output(['git', '-C', str(repo), 'rev-parse', 'HEAD'], text=True).strip()
            bad.unlink(); subprocess.run(['git', '-C', str(repo), 'add', '-u'], check=True); subprocess.run(['git', '-C', str(repo), 'commit', '-qm', 'delete'], check=True)
            result = subprocess.run([sys.executable, str(SCRIPT), '--repo-root', str(repo), '--base', base], text=True, capture_output=True, check=False)
            self.assertEqual(result.returncode, 2); self.assertIn('forbidden Solana path', result.stdout)
        release = (ROOT / 'ci' / 'release-gates.sh').read_text()
        self.assertIn('check_base_v3_release_scope.py', release); self.assertIn('--require-clean', release)

if __name__ == '__main__': unittest.main()


class BaseV3AuditHandoffScopeTest(unittest.TestCase):
    def test_root_audit_handoff_is_outside_base_candidate_allowlist(self):
        errors = MODULE.scope_errors(["base_v3_final_reaudit_handoff_20260824.md"])
        self.assertEqual(errors, ["Base-only candidate includes path outside explicit allowlist: base_v3_final_reaudit_handoff_20260824.md"])
