"""Offline controller demo. Python 3.10+, standard library; no model or network.
Run: python3 order_agent_demo.py
The scripted policy tests orchestration, not language-model quality.
"""
import copy
import json
import re

ORDERS = {'O-1042': {'customer_id': 'C-7', 'status': 'shipped', 'version': 3,
                     'shipment_id': 'L-88'}}
SNAPSHOT_AT = '2026-10-09T00:00:00Z'
SHIPMENTS = {'L-88': {'status': 'collected', 'version': 2}}


def execute(name, arguments, authenticated_customer):
    if name not in {'get_order', 'get_shipment'}:
        return {'ok': False, 'code': 'UNKNOWN_TOOL'}
    if (not isinstance(arguments, dict) or set(arguments) != {'order_id'}
            or not isinstance(arguments['order_id'], str)
            or not re.fullmatch(r'O-[0-9]{1,8}', arguments['order_id'])):
        return {'ok': False, 'code': 'INVALID_ARGUMENT'}
    order_id = arguments['order_id']
    order = ORDERS.get(order_id)
    if order is None or order['customer_id'] != authenticated_customer:
        return {'ok': False, 'code': 'NOT_FOUND'}
    if name == 'get_order':
        return {'ok': True, 'status': order['status'], 'version': order['version'],
                'observed_at': SNAPSHOT_AT,
                'evidence_id': f'order:{order_id}:v{order["version"]}'}
    shipment_id = order['shipment_id']
    shipment = SHIPMENTS.get(shipment_id)
    if shipment is None:
        return {'ok': False, 'code': 'NOT_FOUND'}
    return {'ok': True, **shipment, 'observed_at': SNAPSHOT_AT,
            'evidence_id': f'shipment:{shipment_id}:v{shipment["version"]}'}


def scripted_policy(observations):
    if not observations:
        return {'type': 'tool', 'call_id': 'call-1', 'name': 'get_order',
                'arguments': {'order_id': 'O-1042'}}
    if len(observations) == 1:
        return {'type': 'tool', 'call_id': 'call-2', 'name': 'get_shipment',
                'arguments': {'order_id': 'O-1042'}}
    return {'type': 'final', 'answer': '订单已发货，物流记录尚未显示派送。',
            'evidence_ids': ['order:O-1042:v3', 'shipment:L-88:v2']}


def run(policy, authenticated_customer, max_steps=4):
    if type(max_steps) is not int or max_steps < 1:
        raise ValueError('max_steps must be a positive integer')
    observations, seen_calls = [], set()

    def result(status, **extra):
        return {'status': status, 'observations': observations, **extra}

    for _ in range(max_steps):
        # Isolate the controller record from accidental policy-side mutation.
        action = policy(copy.deepcopy(observations))
        if not isinstance(action, dict):
            return result('invalid_action')
        if action.get('type') == 'final':
            if set(action) != {'type', 'answer', 'evidence_ids'}:
                return result('invalid_action')
            refs = action['evidence_ids']
            available = {o['result']['evidence_id'] for o in observations if o['result']['ok']}
            names = {o['name'] for o in observations if o['result']['ok']}
            if (not isinstance(action['answer'], str) or not action['answer'].strip()
                    or not isinstance(refs, list) or not refs
                    or any(not isinstance(ref, str) for ref in refs)
                    or set(refs) != available
                    or names != {'get_order', 'get_shipment'}):
                return result('invalid_completion')
            # Checks evidence presence only; does not prove answer semantics.
            return result('completed', answer=action['answer'], evidence_ids=refs)
        if (action.get('type') != 'tool'
                or set(action) != {'type', 'call_id', 'name', 'arguments'}
                or not isinstance(action['call_id'], str) or not action['call_id']
                or action['call_id'] in seen_calls
                or not isinstance(action['name'], str)):
            return result('invalid_action')
        seen_calls.add(action['call_id'])
        observation = execute(action['name'], action['arguments'], authenticated_customer)
        observations.append({'call_id': action['call_id'], 'name': action['name'],
                             'result': observation})
        if not observation['ok']:
            return result('failed')
    return result('budget_exceeded')


if __name__ == '__main__':
    print(json.dumps(run(scripted_policy, 'C-7'), ensure_ascii=False, indent=2))
