#!/usr/bin/env python3
from __future__ import annotations

import importlib.util
import json
import tempfile
import unittest
from pathlib import Path

HERE = Path(__file__).resolve().parent
SCRIPT = HERE.parent / "enroll-node.py"
spec = importlib.util.spec_from_file_location("phase2_enroll_node", SCRIPT)
assert spec and spec.loader
module = importlib.util.module_from_spec(spec)
spec.loader.exec_module(module)


class OrchestratorTests(unittest.TestCase):
    def fixture(self):
        return HERE / "fixtures/phase2-debian4.json"

    def test_tailscale_parser_is_deterministic(self):
        doc = {
            "Self": {"HostName": "control", "DNSName": "control.ts.net.", "TailscaleIPs": ["100.64.0.1"]},
            "Peer": {
                "b": {"HostName": "debian4", "DNSName": "debian4.ts.net.", "TailscaleIPs": ["100.64.44.44"], "Online": True}
            },
        }
        first = module.parse_tailscale_status(doc)
        second = module.parse_tailscale_status(doc)
        self.assertEqual(first, second)
        self.assertEqual(first[1]["dns_name"], "debian4.ts.net")

    def test_cluster_parser_requires_items(self):
        with self.assertRaises(module.Phase2Error):
            module.parse_cluster_nodes({})

    def test_dry_run_success_and_apply_rejected(self):
        repo = HERE.parents[2]
        with tempfile.TemporaryDirectory() as tmp:
            receipt = Path(tmp) / "receipt"
            rc = module.main([
                "debian4", "--mode", "dry-run", "--repo-root", str(repo),
                "--fixture", str(self.fixture()), "--receipt-dir", str(receipt),
                "--lock-file", str(Path(tmp) / "lock"),
            ])
            self.assertEqual(rc, 0)
            result = json.loads((receipt / "phase2-result.json").read_text())
            self.assertTrue(result["git_publication_allowed"])
            self.assertFalse(result["live_mutation_performed"])
        with tempfile.TemporaryDirectory() as tmp:
            rc = module.main([
                "debian4", "--mode", "apply", "--repo-root", str(repo),
                "--fixture", str(self.fixture()), "--receipt-dir", str(Path(tmp) / "receipt"),
                "--lock-file", str(Path(tmp) / "lock"),
            ])
            self.assertEqual(rc, 2)

    def test_candidate_mismatch_fails_closed(self):
        repo = HERE.parents[2]
        with tempfile.TemporaryDirectory() as tmp:
            receipt = Path(tmp) / "receipt"
            rc = module.main([
                "other", "--mode", "dry-run", "--repo-root", str(repo),
                "--fixture", str(self.fixture()), "--receipt-dir", str(receipt),
                "--lock-file", str(Path(tmp) / "lock"),
            ])
            self.assertEqual(rc, 2)
            result = json.loads((receipt / "phase2-result.json").read_text())
            self.assertFalse(result["git_publication_allowed"])


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