"""Run `python check.py`; expected failures until starter is implemented.
Run `python check.py --reference` only to inspect the worked-solution feedback.
"""
import importlib
import sys
import unittest
from unittest.mock import patch

sys.dont_write_bytecode = True
module = importlib.import_module("reference" if "--reference" in sys.argv else "starter")
records = {
    "P": {"id": "P", "time": "10:00", "scope": "public"},
    "R": {"id": "R", "time": "09:00", "scope": "staff"},
}

class WorkflowChecks(unittest.TestCase):
    def test_request_contract(self):
        self.assertEqual(module.parse_request({"id": "P"}), {"id": "P"})
        for value in ({}, {"id": ""}, {"id": " "}, {"id": 7}, {"id": "P", "admin": True}, []):
            with self.subTest(value=value):
                self.assertIsNone(module.parse_request(value))

    def test_shape_truth_and_status(self):
        source = records["P"]
        self.assertTrue(module.validate_answer({"status": "ok", "payload": {"id": "P", "time": "10:00"}}, source))
        for envelope in (
            {"status": "ok", "payload": {"id": "P", "time": "11:00"}},
            {"status": "ok", "payload": {"id": "P", "time": "10:00", "extra": 1}},
            {"status": "ok", "payload": {"id": "P", "time": 1000}},
            {"status": "refused"}, {"status": "incomplete"}, None,
        ):
            with self.subTest(envelope=envelope):
                self.assertFalse(module.validate_answer(envelope, source))

    def test_permission_missing_and_invalid(self):
        self.assertEqual(module.lookup("guest", {"id": "P"}, records)["status"], "ok")
        denied = module.lookup("guest", {"id": "R"}, records)
        self.assertEqual(denied, {"status": "denied"})
        self.assertEqual(module.lookup("guest", {"id": "absent"}, records), {"status": "missing"})
        self.assertEqual(module.lookup("guest", {"id": "P", "admin": True}, records), {"status": "invalid"})
        self.assertEqual(module.lookup("staff", {"id": "R"}, records)["status"], "ok")

    def test_retry_does_not_repeat_operation(self):
        cache, calls = {}, []
        def operation():
            calls.append("executed")
            return {"result": len(calls)}
        first = module.once("K", operation, cache)
        self.assertEqual(module.once("K", operation, cache), first)
        self.assertEqual(len(calls), 1)
        module.once("L", operation, cache)
        self.assertEqual(len(calls), 2)

    def test_integrated_artifact_and_new_case(self):
        self.assertEqual(module.run("guest", {"id": "P"}, records, "public", {}), {"status": "ok", "artifact": {"id": "P", "time": "10:00"}})
        self.assertEqual(module.run("guest", {"id": "R"}, records, "restricted", {}), {"status": "denied"})
        self.assertEqual(module.run("guest", {"id": "absent"}, records, "absent", {}), {"status": "missing"})
        self.assertEqual(module.run("guest", {"id": "P", "admin": True}, records, "extra", {}), {"status": "invalid"})
        self.assertEqual(module.run("guest", {"id": ""}, records, "empty", {}), {"status": "invalid"})
        extended = {**records, "N": {"id": "N", "time": "14:15", "scope": "public"}}
        self.assertEqual(module.run("guest", {"id": "N"}, extended, "new", {}), {"status": "ok", "artifact": {"id": "N", "time": "14:15"}})

    def test_capstone_cache_bound_to_current_intent(self):
        cache = {}
        with patch.object(module, "validate_answer", wraps=module.validate_answer) as validate:
            first = module.run("guest", {"id": "P"}, records, "K", cache)
            self.assertEqual(module.run("guest", {"id": "P"}, records, "K", cache), first)
            self.assertEqual(validate.call_count, 1)
        changed = {**records, "P": {**records["P"], "time": "11:00"}}
        self.assertEqual(module.run("guest", {"id": "P"}, changed, "K", cache), {"status": "key_conflict"})
        self.assertEqual(module.run("guest", {"id": "P"}, changed, "L", cache)["artifact"]["time"], "11:00")
        revoked = {**records, "P": {**records["P"], "scope": "staff"}}
        self.assertEqual(module.run("guest", {"id": "P"}, revoked, "K", cache), {"status": "denied"})
        first["artifact"]["time"] = "corrupted"
        self.assertEqual(module.run("guest", {"id": "P"}, records, "K", cache)["artifact"]["time"], "10:00")

if __name__ == "__main__":
    print("Mode:", "worked reference (not learner completion)" if "--reference" in sys.argv else "learner starter (unfinished checks are expected to fail)", flush=True)
    suite = unittest.defaultTestLoader.loadTestsFromTestCase(WorkflowChecks)
    result = unittest.TextTestRunner(verbosity=2).run(suite)
    sys.exit(0 if result.wasSuccessful() else 1)
