"""ParcelOps offline training lab. Python 3.10+; standard library only.

Run: python3 parcelops_offline.py
No network, model calls, credentials, persistent writes or real incident systems.
The in-memory idempotency simulation is NOT crash-safe or multi-process safe.
These tests verify fixture contracts, not SDK integration or production security.
"""
import hashlib
import json
import re
import unittest

RECORDS = {
    ("tenant-a", "INC-104"): {"status": "delayed", "revision": 7},
    ("tenant-b", "INC-205"): {"status": "resolved", "revision": 2},
}


def lookup(tenant, incident_id):
    if not re.fullmatch(r"INC-\d+", incident_id):
        raise ValueError("Invalid incident ID")
    value = RECORDS.get((tenant, incident_id))
    return dict(value) if value else None


def verify(answer, tenant, writes):
    record = lookup(tenant, answer.get("incident_id", "INC-0"))
    return bool(record and answer.get("status") == record["status"]
                and answer.get("revision") == record["revision"]
                and answer.get("evidence_ids") == [answer["incident_id"]]
                and not writes)


def intent_hash(intent):
    return hashlib.sha256(json.dumps(intent, sort_keys=True,
                                    separators=(",", ":")).encode()).hexdigest()


def approval_matches(approval, intent, reviewer, current_revision, now):
    return bool(approval["reviewer"] == reviewer
                and approval["intent_hash"] == intent_hash(intent)
                and approval["expires_at"] > now
                and intent["expected_revision"] == current_revision)


class MemoryLedger:
    """Teaching simulation only; no concurrency, durability or authentication."""
    def __init__(self):
        self.completed = {}
        self.notes = []

    def append(self, request_key, intent):
        digest = intent_hash(intent)
        if request_key in self.completed:
            prior_digest, result = self.completed[request_key]
            if digest != prior_digest:
                raise ValueError("Key reused with different intent")
            return result
        self.notes.append(dict(intent))
        result = len(self.notes)
        self.completed[request_key] = (digest, result)
        return result


class ContractTests(unittest.TestCase):
    def setUp(self):
        self.answer = {"incident_id": "INC-104", "status": "delayed",
                       "revision": 7, "evidence_ids": ["INC-104"]}
        self.intent = {"operation": "append_note", "incident_id": "INC-104",
                       "text": "Check carrier scan", "expected_revision": 7}
        self.approval = {"reviewer": "operator-a", "intent_hash": intent_hash(self.intent),
                         "expires_at": 200}

    def test_known_incident(self):
        self.assertEqual(lookup("tenant-a", "INC-104")["status"], "delayed")

    def test_unknown_incident(self):
        self.assertIsNone(lookup("tenant-a", "INC-999"))

    def test_tenant_boundary(self):
        self.assertIsNone(lookup("tenant-b", "INC-104"))

    def test_invalid_identifier(self):
        with self.assertRaises(ValueError):
            lookup("tenant-a", "../INC-104")

    def test_supported_answer(self):
        self.assertTrue(verify(self.answer, "tenant-a", []))

    def test_unsupported_status(self):
        self.assertFalse(verify({**self.answer, "status": "resolved"}, "tenant-a", []))

    def test_stale_revision(self):
        self.assertFalse(verify({**self.answer, "revision": 6}, "tenant-a", []))

    def test_missing_evidence(self):
        self.assertFalse(verify({**self.answer, "evidence_ids": []}, "tenant-a", []))

    def test_forbidden_write(self):
        self.assertFalse(verify(self.answer, "tenant-a", ["unexpected-write"]))

    def test_repeat_key_one_effect(self):
        ledger = MemoryLedger()
        self.assertEqual(ledger.append("req-1", self.intent), ledger.append("req-1", self.intent))
        self.assertEqual(len(ledger.notes), 1)

    def test_key_cannot_change_intent(self):
        ledger = MemoryLedger()
        ledger.append("req-1", self.intent)
        with self.assertRaises(ValueError):
            ledger.append("req-1", {**self.intent, "text": "Mark resolved"})

    def test_valid_approval(self):
        self.assertTrue(approval_matches(self.approval, self.intent, "operator-a", 7, 100))

    def test_changed_approval_payload(self):
        self.assertFalse(approval_matches(self.approval, {**self.intent, "text": "changed"}, "operator-a", 7, 100))

    def test_wrong_reviewer(self):
        self.assertFalse(approval_matches(self.approval, self.intent, "operator-b", 7, 100))

    def test_expired_approval(self):
        self.assertFalse(approval_matches(self.approval, self.intent, "operator-a", 7, 201))

    def test_stale_target(self):
        self.assertFalse(approval_matches(self.approval, self.intent, "operator-a", 8, 100))


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