#!/usr/bin/env python3
"""Strict B/C fixture projection comparison; no broad key/type normalization."""
import importlib.util
import json
from pathlib import Path
import sys

here = Path(__file__).resolve().parent
comparator = here.parents[2] / 'work/2026-09-28-smart-canteen-dm8-poc/http-harness/strict_response_compare.py'
spec = importlib.util.spec_from_file_location('strict_compare', comparator)
strict = importlib.util.module_from_spec(spec)
spec.loader.exec_module(strict)

def checked(path, lane):
    data = strict.load_json(path)
    assert data['lane'] == lane and data['boundary_verified'] is True
    assert data['case_count'] == len(data['cases']) == 18 and data['error'] is None
    cleanup = data['cleanup']
    assert cleanup == {'fresh_pdo_owned_rows': 0, 'owned_relation_rows': 0,
                       'token_absent': True, 'existing_categories_unchanged': True}
    assert len({c['scenario'] for c in data['cases']}) == 18
    assert all(c['trace_format_valid'] is True and c['http_status'] == 200 for c in data['cases'])
    if 'form_encoding_scenarios' in data:
        forms = data['form_encoding_scenarios']
        assert len(forms) == 4
        assert [f['body']['status'] for f in forms] == [200, 500, 200, 500]
        assert all(f['http_status'] == 200 and f['trace_format_valid'] is True for f in forms)
        assert all(f['body']['message'] == '上级分类不允许设置为当前子分类'
                   and f['independent_state']['cycle_not_written'] is True for f in forms[1::2])
    else:
        assert len(data['form_encoding_findings']) == 2
        assert all(f['business_status'] == 500 and f['strict_parent_id_type_error'] is True
                   and f['original_row_unchanged'] is True for f in data['form_encoding_findings'])
    return data

def main():
    b, c = checked(sys.argv[1], 'B'), checked(sys.argv[2], 'C')
    differences = strict.compare(b['cases'], c['cases'])
    form_key = 'form_encoding_scenarios' if 'form_encoding_scenarios' in b else 'form_encoding_findings'
    differences += strict.compare(b[form_key], c[form_key], '$.' + form_key)
    stats = {}
    for lane, data in [('B', b), ('C', c)]:
        events = [e for e in data['events'] if e.get('kind') == 'query_observed']
        stats[lane] = {'observed_queries': len(events),
                       'fingerprints': len({e['fingerprint'] for e in events}),
                       'callsites': sorted({s for e in events for s in e['callsites']}),
                       'operations': {op: sum(e['operation'] == op for e in events)
                                      for op in ['select', 'insert', 'update', 'delete', 'other']},
                       'cleanup': data['cleanup']}
        stats[lane]['request_end_events'] = sum(e.get('kind') == 'request_end' for e in data['events'])
    output = {'status': 'PASS' if not differences else 'FAIL', 'cases': 18,
              'form_cases': len(b.get('form_encoding_scenarios', [])),
              'total_comparable_scenarios': 18 + len(b.get('form_encoding_scenarios', [])),
              'unique_method_paths': sorted({c['method'] + ' ' + c['path'] for c in b['cases']}),
              'differences': differences, 'lanes': stats,
              'form_encoding_fix_verified': form_key == 'form_encoding_scenarios',
              'shared_baseline_input_defects': b.get('form_encoding_findings', []),
              'scope': 'actual CRUD plus hierarchy rejection; list owned subtree only, not all natural snapshot data'}
    print(json.dumps(output, ensure_ascii=False, indent=2, default=str))
    return bool(differences)

if __name__ == '__main__':
    raise SystemExit(main())
