#!/usr/bin/env python3
import hashlib, json, sys

def canon(x):
    return json.dumps(x, sort_keys=True, separators=(',', ':'), ensure_ascii=False).encode()
def digest(x):
    return hashlib.sha256(canon(x)).hexdigest()
def fail(code, msg):
    print(json.dumps({'ok':False,'code':code,'error':msg}, sort_keys=True)); return 1

def produce_effect(consumed, current_head, effect_payload):
    if consumed.get('state') != 'RESUME_CONSUMED':
        return None, ('RECEIPT_NOT_CONSUMED', 'effect path accepts only RESUME_CONSUMED')
    if consumed.get('validated_head_hash') != current_head:
        return None, ('HEAD_BINDING_MISMATCH', 'current head differs from validated head')
    consumption_id = consumed.get('consumption_id')
    if not isinstance(consumption_id, str) or not consumption_id:
        return None, ('MISSING_CONSUMPTION_ID', 'consumption_id is required')
    effect = {
        'effect_payload': effect_payload,
        'consumption_id': consumption_id,
        'consumed_head_hash': current_head,
        'effect_preimage_hash': digest({'effect_payload': effect_payload, 'consumption_id': consumption_id, 'consumed_head_hash': current_head})
    }
    return effect, None

def main():
    good = {'state':'RESUME_CONSUMED','validated_head_hash':'head-A','consumption_id':'cons-001'}
    effect, err = produce_effect(good, 'head-A', {'action':'send_next_gate'})
    if err: return fail(*err)
    tests = []
    # Negative control 1: alternate valid receipt must create a distinct identity.
    alt, err = produce_effect({**good, 'consumption_id':'cons-002'}, 'head-A', {'action':'send_next_gate'})
    tests.append(('alternate_receipt_changes_identity', not err and alt['effect_preimage_hash'] != effect['effect_preimage_hash']))
    # Negative control 2: stale/mutated head refuses before persistence.
    stale, err = produce_effect(good, 'head-B', {'action':'send_next_gate'})
    tests.append(('mutated_head_refuses', stale is None and err and err[0] == 'HEAD_BINDING_MISMATCH'))
    # Negative control 3: READY cannot produce an effect.
    ready, err = produce_effect({**good, 'state':'RESUME_READY'}, 'head-A', {'action':'send_next_gate'})
    tests.append(('ready_refuses', ready is None and err and err[0] == 'RECEIPT_NOT_CONSUMED'))
    # Replay is idempotent at the same preimage: same receipt + payload => same effect identity.
    replay, err = produce_effect(good, 'head-A', {'action':'send_next_gate'})
    tests.append(('replay_same_identity', not err and replay['effect_preimage_hash'] == effect['effect_preimage_hash']))
    if not all(ok for _, ok in tests):
        return fail('NEGATIVE_CONTROL_FAILED', str(tests))
    print(json.dumps({'ok':True,'effect':effect,'tests':tests}, sort_keys=True)); return 0
if __name__ == '__main__': sys.exit(main())
