#!/usr/bin/env python3
"""Verify only structure/aggregates/constants; no natural-row or DB access."""
import hashlib
import json
import re
from pathlib import Path
root=Path(__file__).parent;private=root/'private-evidence'
read=lambda name:json.loads((private/name).read_text())
b=read('B-fresh.json');c=read('C-fresh.json')
seven={'dingtalk_avatar','update_time','dingtalk_userid','primary_department_uuid','dingtalk_last_seen_full_batch_id','dingtalk_sync_time','dingtalk_sync_md5'}
bc={column['column_name']:column for column in b['columns']};cc={column['column_name'].lower():column for column in c['columns']}
assert set(bc)-set(cc)==seven and set(cc)-set(bc)==set()
assert len(bc)==77 and len(cc)==70
assert b['row_count'][0]['cnt']==40930 and c['row_count'][0]['cnt']==2103
assert b['triggers']==c['triggers']==[] and c['foreign_keys']==[]
assert {row['constraint_type'] for row in b['constraints']}=={'PRIMARY KEY','UNIQUE'}
assert len(c['constraints'])==1 and c['constraints'][0]['constraint_type']=='P'
assert len([column for column in c['columns']if column['nullable']=='Y'])==10
assert len([column for column in b['columns']if column['is_nullable']=='YES'])==13
assert bc['dingtalk_userid']['collation_name']=='utf8mb4_bin' and bc['dingtalk_sync_md5']['collation_name']=='ascii_bin'
assert bc['dingtalk_last_seen_full_batch_id']['column_type']=='bigint(20) unsigned'
assert bc['update_time']['datetime_precision']==0 and bc['update_time']['extra'].lower()=='on update current_timestamp'
assert bc['dingtalk_sync_time']['datetime_precision']==0
assert cc['sport_event_uuid']['data_type']=='CLOB'
assert c['constant_null_empty'][0]['equal_value']==0
assert c['byte_constants'][0]=={'utf8_hex':'C3A9','chars':1,'bytes':2,'empty_bytes':0,'null_bytes':None}
literal=read('C-constants.json');bound=read('C-bound-constants.json')
assert literal['tests']['case_flag'][0]['flag']==0
assert literal['tests']['clob_long_last_case'][0]=={'lob_length':68001,'cmp':0}
assert literal['tests']['nlssort_case'][0]['eq']==1 and literal['tests']['nlssort_tail'][0]['eq']==0
assert literal['tests']['hex_pad_key'][0]['case_eq']==1
assert bound['tests']['hex_pad_case'][0]['eq']==0 and bound['tests']['hex_pad_tail'][0]['eq']==1
assert bound['tests']['binary_pad_case'][0]['eq']==0 and bound['tests']['binary_pad_tail'][0]['eq']==1
assert bound['tests']['clob_chunk_hex_case'][0]=={'h1':'41','h2':'61'}
for value in ['0','9007199254740991','9007199254740993','9223372036854775807','18446744073709551615']:
 assert literal['tests']['uint64_'+value]['native'][0]['exact_value']==value
assert literal['tests']['uint64_9007199254740993']['native'][0]['native_value']==9007199254740992.0
sql=(root/'staff-time-trigger-proposal.sql').read_text()
assert set(re.findall(r'^    -- ([A-Z0-9_]+)$',sql,re.M))=={name.upper()for name in set(bc)-{'update_time','sport_event_uuid'}}
assert 'DBMS_LOB.COMPARE'not in sql and 'V_OFFSET := V_OFFSET + 256' in sql
assert "NOT UPDATING('UPDATE_TIME')"in sql and "UPDATING('SPORT_EVENT_UUID')"in sql
assert hashlib.sha256((root/'probe-character-unique-uint64-proposal.json').read_bytes()).hexdigest()=='b38252b664d4e4d401579cf00eaeab3bce4563fc258e96a4ffc5fbd01d9e9bc9'
attempts={'B':0,'C':0};success={'B':0,'C':0}
for file in private.glob('*.json'):
 item=json.loads(file.read_text())
 if 'journal'not in item:continue
 assert item['DML']==item['HTTP']==0
 # C-fresh used DDL as a SELECT GET_DDL metadata key, not an executed counter.
 if file.name=='C-fresh.json':assert isinstance(item['DDL'],list)
 else:assert item['DDL']==0
 for entry in item['journal']:
  assert entry['SQL'].startswith('SELECT ')
  attempts[item['lane']]+=1;success[item['lane']]+=int(entry.get('ok',False))
print(json.dumps({'passed':True,'DML':0,'DDL':0,'HTTP':0,'natural_personal_rows_exported':0,'columns_B_C':[77,70],'missing':sorted(seven),'rows_B_C':[40930,2103],'SELECT_attempts':attempts,'SELECT_success':success,'expected_read_errors_C':2,'time_trigger_scalar_coverage':75,'CLOB_loop_candidate_not_compiled':True,'probe_not_authorized_not_run':True},ensure_ascii=False,indent=2))
