"""Exact authored message contract checks; not generic spoken-URL equivalence."""
from pathlib import Path
from urllib.parse import urlsplit
import json,copy
def validate(message,targets):
    if message['id'] not in targets or message['raw_target']!=targets[message['id']]:raise ValueError('canonical target changed')
    if message['channel'] not in ('web','voice') or not message['spoken'].strip() or not message['display'].strip():raise ValueError('channel and nonempty copy required')
    target=urlsplit(message['raw_target'])
    if target.scheme=='https':
        if target.hostname!='example.com' or target.username or target.password:raise ValueError('reserved authored HTTP target required')
    elif target.scheme=='mailto':
        if not target.path.endswith('@example.com') or target.query or target.fragment:raise ValueError('local teaching email profile')
    else:raise ValueError('unsupported target scheme')
    action=message['next_action'];available=message['channel']=='web' or message['alternate_channel_confirmed'] is True
    if action in ('open_attached_link','click_below') and not available:raise ValueError('no visual/confirmed alternate delivery path')
    if action=='sent_already' and message['alternate_channel_confirmed'] is not True:raise ValueError('delivery has not been confirmed')
    if action not in ('open_attached_link','click_below','read_back_address','sent_already'):raise ValueError('unknown next action')
    return True
if __name__=='__main__':
    data=json.loads(Path(__file__).with_name('tts-address-action-contracts.json').read_text(encoding='utf-8'));targets=data['canonical_targets'];messages=data['messages']
    assert len(messages)==4 and all(validate(m,targets) for m in messages)
    wrong=[]
    a=copy.deepcopy(messages[0]);a['raw_target']=a['raw_target'].lower();wrong.append(('changed_path_case',a))
    a=copy.deepcopy(messages[3]);a['raw_target']=a['raw_target'].replace('007','7');wrong.append(('lost_leading_zeros',a))
    a=copy.deepcopy(messages[1]);a['next_action']='click_below';wrong.append(('voice_link_below',a))
    a=copy.deepcopy(messages[1]);a['next_action']='sent_already';wrong.append(('unconfirmed_delivery_claim',a))
    for name,m in wrong:
        try:validate(m,targets)
        except ValueError:pass
        else:raise AssertionError(name+' accepted')
    assert targets['item'].endswith('R-007%2FA')
    print(json.dumps({'valid_authored_messages':4,'rejected_mutations':[name for name,_ in wrong],'canonical_targets_preserved':targets,'semantic_equivalence_of_speech_proven':False,'message_sent':False,'TTS_or_browser_navigation_run':False},ensure_ascii=False,indent=2))
