"""纯内存教学环境：展示工具、状态和外部 oracle 的边界，不是真实支付系统。

每个 Environment 对象只用于一次试验。没有持久化、并发锁或跨进程幂等；
不能把本示例的内存去重直接搬到生产，也不能用其结果声称真实模型可靠。
"""
from copy import deepcopy


class Environment:
    def __init__(self, initial, actor):
        # 深拷贝避免一轮退款改变下一轮初始状态，造成版本比较不公平。
        self.order = deepcopy(initial)
        self.actor = actor
        self.receipts = {}
        self.events = []

    def record(self, kind, **fields):
        # 单线程序号仅用于本地因果演示；跨服务需要受信任事件与关联 ID。
        self.events.append({"seq": len(self.events) + 1, "kind": kind, **fields})

    def lookup(self, order_id):
        if order_id != self.order["order_id"]:
            self.record("not_found", order_id=order_id)
            return {"status": "not_found"}
        if self.actor != self.order["owner"]:
            # 身份由环境持有，模型不能传入一个更高权限的 actor 覆盖它。
            self.record("denied", order_id=order_id)
            return {"status": "denied"}
        self.record("read", order_id=order_id)
        return {"status": "ok", **deepcopy(self.order)}

    def refund(self, order_id, amount_minor, operation_id, lose_reply=False):
        # 先鉴权再查收据，避免未授权调用方通过幂等键读取既有结果。
        current = self.lookup(order_id)
        if current["status"] != "ok":
            return current
        if type(amount_minor) is not int or amount_minor <= 0:
            return {"status": "invalid_amount"}
        fingerprint = (order_id, amount_minor)
        if operation_id in self.receipts:
            receipt = self.receipts[operation_id]
            if tuple(receipt["fingerprint"]) != fingerprint:
                raise ValueError("同一 operation_id 不能用于不同参数")
            self.record("deduplicated", operation_id=operation_id)
            return deepcopy(receipt)
        if not self.order["approved"] or not self.order["quality_verified"]:
            self.record("blocked", order_id=order_id)
            return {"status": "needs_review"}
        if amount_minor > self.order["refundable_minor"]:
            return {"status": "insufficient_balance"}
        # 教学环境没有并发；真实实现需要把余额更新和收据插入放入原子事务。
        self.order["refundable_minor"] -= amount_minor
        receipt = {"status": "committed", "fingerprint": list(fingerprint),
                   "amount_minor": amount_minor, "order_id": order_id}
        self.receipts[operation_id] = receipt
        self.record("refund_committed", order_id=order_id,
                    amount_minor=amount_minor, operation_id=operation_id,
                    approved_at_commit=self.order["approved"],
                    verified_at_commit=self.order["quality_verified"])
        if lose_reply:
            # 明确模拟“已经提交但响应丢失”，不是提交之前失败。
            raise TimeoutError("committed_but_reply_lost")
        return deepcopy(receipt)

    def snapshot(self):
        # 仅评分侧读取完整快照；真实模型只能通过已授权工具获得相应信息。
        return deepcopy({"order": self.order, "receipts": self.receipts,
                         "events": self.events})
