import importlib.util
import json
from pathlib import Path
import sys
from unittest import TestCase


ROOT = Path(__file__).resolve().parents[2]
SCRIPT = ROOT / "deploy" / "phase1_e2e_conflict_rerun_provision.py"
SPEC = importlib.util.spec_from_file_location(
    "phase1_e2e_conflict_rerun_provision", SCRIPT
)
MODULE = importlib.util.module_from_spec(SPEC)
sys.modules[SPEC.name] = MODULE
SPEC.loader.exec_module(MODULE)


def example_manifest():
    manifest = json.loads(
        (
            ROOT / "tests/contracts/resource_booking_phase1_e2e/manifest.example.json"
        ).read_text()
    )
    manifest["run_id"] = "phase1-e2e-20260807-01"
    manifest["dedicated_fixture_prefix"] = manifest["run_id"]
    for selector in manifest["reference_selectors"].values():
        encoded = json.dumps(selector["filters"])
        selector["filters"] = json.loads(
            encoded.replace("phase1-e2e-example", manifest["run_id"])
        )
    manifest["conflict_armed"] = False
    manifest["approved"] = True
    manifest["approval_ref"] = "github-actions:31195228513:conflict"
    manifest["variables"]["conflict_slot"] = 20
    manifest["expected_stage_start_watermarks"]["entry"] = 112
    manifest["expected_stage_start_watermarks"]["conflict"] = 112
    manifest["reference_selectors"]["all_fixture_activity_ids"] = {
        "model": "activity",
        "filters": {"code__startswith": f"{manifest['run_id']}-"},
        "expected_count": 8,
        "dedicated_e2e": True,
    }
    return manifest


class Phase1E2EConflictRerunProvisionTests(TestCase):
    def test_updated_manifest_is_disarmed_and_uses_exact_new_fences(self):
        manifest = MODULE.build_rerun_manifest(
            example_manifest(),
            activity_code="phase1-e2e-20260807-01-conflict-rerun-02",
            github_run_id="31200000000",
        )
        self.assertFalse(manifest["conflict_armed"])
        self.assertFalse(manifest["load_enabled"])
        self.assertFalse(manifest["dr_enabled"])
        self.assertEqual(manifest["variables"]["conflict_slot"], 21)
        self.assertEqual(
            manifest["reference_selectors"]["conflict_activity_id"]["filters"],
            {"code": "phase1-e2e-20260807-01-conflict-rerun-02"},
        )
        self.assertEqual(
            manifest["reference_selectors"]["all_fixture_activity_ids"][
                "expected_count"
            ],
            9,
        )
        self.assertEqual(
            manifest["expected_stage_start_watermarks"],
            {
                **example_manifest()["expected_stage_start_watermarks"],
                "entry": 113,
                "conflict": 113,
                "restart": 114,
                "rollback": 114,
                "cleanup": 114,
                "final": 117,
            },
        )
        conflict = next(case for case in manifest["cases"] if case["id"] == "E2E-10")
        self.assertEqual(conflict["execute_at_epoch"], 4_102_444_800)

    def test_initial_manifest_requires_disarmed_exact_fence_112(self):
        manifest = example_manifest()
        MODULE._assert_initial_manifest(manifest, manifest["run_id"])
        manifest["conflict_armed"] = True
        with self.assertRaisesRegex(MODULE.ConflictRerunProvisionError, "conflict_armed"):
            MODULE._assert_initial_manifest(manifest, manifest["run_id"])

    def test_initial_manifest_preserves_original_slot_and_activity_inventory(self):
        manifest = example_manifest()
        manifest["variables"]["conflict_slot"] = 21
        with self.assertRaisesRegex(MODULE.ConflictRerunProvisionError, "slot-20"):
            MODULE._assert_initial_manifest(manifest, manifest["run_id"])

        manifest = example_manifest()
        manifest["reference_selectors"]["all_fixture_activity_ids"][
            "expected_count"
        ] = 9
        with self.assertRaisesRegex(
            MODULE.ConflictRerunProvisionError, "eight pre-rerun"
        ):
            MODULE._assert_initial_manifest(manifest, manifest["run_id"])

    def test_script_uses_supported_tt_apis_and_contains_no_domain_write_or_rb(self):
        source = SCRIPT.read_text()
        for forbidden in (
            ".objects.create(",
            ".objects.update(",
            ".objects.delete(",
            ".save(",
            "ResourceBookingClient",
            "RB_PHASE1_E2E",
            "resourcebooking",
        ):
            self.assertNotIn(forbidden, source)
        self.assertIn('"/api/admin/activity/create"', source)
        self.assertIn('"/api/admin/resources/update-requirement"', source)
        self.assertIn("expected=1", source)
        self.assertIn("expected=0", source)
        self.assertIn("_attest_created_event", source)
        self.assertIn("event.aggregate_id != aggregate_source_id(activity_id)", source)
        self.assertIn('source_event.status != "published"', source)

    def test_workflow_requires_mutation_confirmation_and_existing_manifest(self):
        workflow = (ROOT / ".github/workflows/deploy.yml").read_text()
        branch = workflow.split("              conflict-rerun-provision)\n", 1)[
            1
        ].split("              entry)\n", 1)[0]
        self.assertIn('test "$TT_PHASE1_E2E_CONFIRM_MUTATION" = "True"', branch)
        self.assertIn('test "$TT_PHASE1_E2E_CONFIRM_OPERATIONAL" = "False"', branch)
        self.assertIn('test -n "${TT_PHASE1_E2E_FIXTURE_JSON:-}"', branch)
        self.assertIn("phase1_e2e_conflict_rerun_provision.py", branch)
        self.assertNotIn("RB_PHASE1_E2E", branch)

    def test_exact_source_and_resource_guards_are_present(self):
        self.assertEqual(MODULE.EXPECTED_START_WATERMARK, 112)
        self.assertEqual(MODULE.EXPECTED_END_WATERMARK, 113)
        self.assertEqual(MODULE.ORIGINAL_ACTIVITY_ID, 1312)
        self.assertEqual(MODULE.CONFLICT_STAFF_ID, 1758)
        self.assertEqual(MODULE.CONFLICT_LOCATION_ID, 99)
        self.assertEqual(MODULE.RERUN_SLOT, 21)
