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

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

class DocumentReferenceGateTest(unittest.TestCase):
    def test_current_package_discovers_root_and_nested_documents(self):
        manifest = json.loads((ROOT / 'base_sepolia_v3_candidate_manifest.json').read_text())
        paths = MODULE.document_paths(ROOT)
        self.assertIn(ROOT / 'README.md', paths)
        self.assertIn(ROOT / 'docs' / 'BASE_SEPOLIA_V3_ENABLED_SURFACE_RUNBOOK.md', paths)
        self.assertTrue(all(MODULE.check(path, MODULE.candidate_marker(manifest)) == [] for path in paths))

    def test_stale_v2_selector_and_wrong_commit_fail(self):
        with tempfile.TemporaryDirectory() as directory:
            path = Path(directory) / 'bad.md'; path.write_text('Candidate-Commit: `old`\nForceExit()\n')
            self.assertEqual(len(MODULE.check(path, 'BLOCKED_NO_FINAL_SOURCE_COMMIT')), 2)

    def test_omitted_and_out_of_package_paths_are_rejected(self):
        with tempfile.TemporaryDirectory() as directory:
            root = Path(directory) / 'package'; (root / 'docs').mkdir(parents=True)
            for name in MODULE.ROOT_DOCUMENTS: (root / name).write_text('Candidate-Commit: `BLOCKED_NO_FINAL_SOURCE_COMMIT`\n')
            nested = root / 'docs' / 'nested' / 'runbook.md'; nested.parent.mkdir(); nested.write_text('Candidate-Commit: `BLOCKED_NO_FINAL_SOURCE_COMMIT`\n')
            paths = MODULE.document_paths(root)
            self.assertIn(nested, paths)
            (root / 'partner-update.md').write_text('Candidate-Commit: `BLOCKED_NO_FINAL_SOURCE_COMMIT`\n')
            with self.assertRaisesRegex(ValueError, 'unexpected root'):
                MODULE.document_paths(root)

    def test_symlink_is_fail_closed(self):
        with tempfile.TemporaryDirectory() as directory:
            root = Path(directory) / 'package'; docs = root / 'docs'; docs.mkdir(parents=True)
            for name in MODULE.ROOT_DOCUMENTS: (root / name).write_text('Candidate-Commit: `BLOCKED_NO_FINAL_SOURCE_COMMIT`\n')
            outside = Path(directory) / 'outside.md'; outside.write_text('Candidate-Commit: `BLOCKED_NO_FINAL_SOURCE_COMMIT`\n')
            os.symlink(outside, docs / 'linked.md')
            with self.assertRaises(ValueError): MODULE.document_paths(root)

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


class DuplicateMarkerManifestTest(unittest.TestCase):
    def test_document_gate_rejects_duplicate_marker_manifest_members(self):
        with tempfile.TemporaryDirectory() as directory:
            root = Path(directory); manifest = root / "manifest.json"
            manifest.write_text('{"candidate":{"sourceCommit":"a","sourceCommit":"b"}}', encoding="utf-8")
            result = subprocess.run([sys.executable, str(ROOT / "scripts" / "check_v3_document_refs.py"), "--manifest", str(manifest), "--package-root", str(root)], text=True, capture_output=True)
            self.assertNotEqual(result.returncode, 0)
            self.assertIn("duplicate", result.stderr + result.stdout)
