#!/usr/bin/env python3
"""Strict complete response comparison for the isolated article-category tenants."""
import importlib.util
import json
from pathlib import Path
import sys

here = Path(__file__).resolve().parent
spec = importlib.util.spec_from_file_location('strict', here.parents[2] / 'work/2026-09-28-smart-canteen-dm8-poc/http-harness/strict_response_compare.py')
strict = importlib.util.module_from_spec(spec)
spec.loader.exec_module(strict)
steps = ['LIST_EMPTY_BEFORE', 'ADD_JSON', 'ADD_FORM', 'LIST_TWO', 'EDIT_FORM',
         'LIST_SORTED', 'DELETE_REFERENCED_REJECT', 'LIST_AFTER_REJECT',
         'DELETE_AFTER_ARTICLE_SOFT_STATE', 'LIST_ONE', 'DELETE_SECOND', 'LIST_EMPTY_AFTER']
expected_scenarios = ['PILOT_AC_' + module + '_' + step for module in ['STORE', 'TERMINAL'] for step in steps]

def checked(path, lane):
    data = strict.load_json(path)
    assert data['lane'] == lane and data['boundary_verified'] is True and data['private_tenant_host_mapping'] is True
    assert data['error'] is None and data['case_count'] == len(data['cases']) == 24
    assert data['metadata'] == {'formal_category_columns_equal': True, 'triggers': 0, 'foreign_keys': 0}
    assert [c['scenario'] for c in data['cases']] == expected_scenarios
    for case in data['cases']:
        assert case['http_status'] == 200 and case['trace_format_valid'] is True
        if case['scenario'].endswith('DELETE_REFERENCED_REJECT'):
            assert case['body']['status'] == 500 and case['body']['message'] == '该分类下存在1个文章，不允许删除'
        else:
            assert case['body']['status'] == 200
    assert data['cleanup'] == {'fresh_pdo_categories': 0, 'fresh_pdo_articles': 0,
                               'tokens_absent': True, 'natural_tables_unchanged': True}
    ends = [e for e in data['events'] if e.get('kind') == 'request_end']
    assert len(ends) == 24 and all(e['fatal'] is False for e in ends)
    return data

def main():
    b, c = checked(sys.argv[1], 'B'), checked(sys.argv[2], 'C')
    def hashes(data):
        result = {}
        for event in data['events']:
            for path, sha in event.get('source_hashes', {}).items():
                assert path not in result or result[path] == sha
                result[path] = sha
        return result
    bh, ch = hashes(b), hashes(c)
    shared = sorted(bh.keys() & ch.keys())
    assert shared and all(bh[path] == ch[path] for path in shared)
    differences = strict.compare(b['cases'], c['cases'])
    lanes = {}
    for lane, data in [('B', b), ('C', c)]:
        queries = [e for e in data['events'] if e.get('kind') == 'query_observed']
        assert all(isinstance(e.get('fingerprint_lexical_warning'), bool) for e in queries)
        lanes[lane] = {'queries': len(queries), 'fingerprints': len({e['fingerprint'] for e in queries}),
                       'fingerprint_lexical_warnings': sum(e['fingerprint_lexical_warning'] for e in queries),
                       'warning_scenarios': sorted({e['scenario'] for e in queries if e['fingerprint_lexical_warning']}),
                       'callsites': sorted({site for e in queries for site in e['callsites']}),
                       'operations': {op: sum(e['operation'] == op for e in queries)
                                      for op in ['select', 'insert', 'update', 'delete', 'other']},
                       'source_snapshot': data['source_before'], 'cleanup': data['cleanup']}
    output = {'status': 'PASS' if not differences else 'FAIL', 'complete_response_case_pairs': 24,
              'success_pairs': 22, 'expected_refusal_pairs': 2,
              'actual_methods_paths': sorted({case['method'] + ' ' + case['path'] for case in b['cases']}),
              'shared_source_files_same_sha': {path: bh[path] for path in shared},
              'differences': differences, 'lanes': lanes,
              'limitations': 'Article soft-delete is PDO fixture state, not HTTP article coverage; no unknown-ID/invalid-length/permission/outage/performance proof'}
    print(json.dumps(output, ensure_ascii=False, indent=2, default=str))
    return bool(differences)

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