#!/usr/bin/env python3
"""Assert MySQL unchanged, and DM changed only at the proven DECIMAL projections."""
from copy import deepcopy
from decimal import Decimal
import importlib.util
import json
from pathlib import Path
import sys

module = Path(__file__).resolve().parents[3] / 'work/2026-09-28-smart-canteen-dm8-poc/http-harness/strict_response_compare.py'
spec = importlib.util.spec_from_file_location('strict', module)
strict = importlib.util.module_from_spec(spec)
spec.loader.exec_module(strict)
if len(sys.argv) != 5:
    raise SystemExit('Expected red-B red-C green-B green-C response files')
red_b, red_c, green_b, green_c = [strict.load_json(p) for p in sys.argv[1:]]
expected = {'ENUM_1','ENUM_2','ENUM_3','ENUM_17','FOODS_ALL','FOODS_LIST','FOODS_CATE','FOODS_DETAIL',
            'DISHES_ALL','DISHES_LIST','DISHES_CATE','DISHES_DETAIL','DISHES_MORE','NATION','SPORT'}
if any(set(data) != expected for data in [red_b, red_c, green_b, green_c]):
    raise SystemExit('Required scenario absent')
nutrition = {'energy','carbohydrate','protein','fat','sfa','mufa','pufa','cholesterol',
    'va','renieratene','retinol','vb1','vb2','vpp','vc','ve','folic_acid','biotin',
    'pantothenic_acid','choline','potassium','sodium','calcium','magnesium','iron',
    'zinc','selenium','iodine','phosphorus','cuprum','manganese','purine','dietary_fiber',
    'moisture','ash','gi','gl'}
rule = {'$["trace_id"]': {'type':'string','pattern':'[0-9a-f]{13}',
    'reason':'Validated framework request trace','require_distinct':True}}

def fixed(row, fields):
    for field in fields:
        if field in row and row[field] is not None:
            row[field] = format(Decimal(str(row[field])), '.2f')

def expected_dm(name, body):
    body = deepcopy(body)
    if name in {'FOODS_LIST','DISHES_LIST'}:
        fields = nutrition if name == 'FOODS_LIST' else nutrition | {'weight','raw_flag_weight'}
        for row in body['data']['list']['data']:
            fixed(row, fields)
    if name in {'FOODS_DETAIL','DISHES_DETAIL'}:
        fields = nutrition if name == 'FOODS_DETAIL' else nutrition | {'weight','raw_flag_weight'}
        row = body['data']['detail']
        fixed(row, fields)
        if name == 'DISHES_DETAIL':
            for food in row.get('foods', []):
                fixed(food, {'foods_weight','foods_ratio'})
    return body

results = []
for name in sorted(expected):
    for data in [red_b,red_c,green_b,green_c]:
        if data[name]['http_status'] != 200 or data[name]['body'].get('status') != 200:
            raise SystemExit('Non-positive scenario: ' + name)
    bd = strict.compare(red_b[name]['body'], green_b[name]['body'], rules=rule)
    cd = strict.compare(expected_dm(name, red_c[name]['body']), green_c[name]['body'], rules=rule)
    results.append({'scenario':name,'mysql_pre_post_differences':len(bd),
        'dm_expected_projection_differences':len(cd)})
print(json.dumps({'cases':results,'cases_count':len(results),
    'mysql_unchanged':not any(x['mysql_pre_post_differences'] for x in results),
    'dm_only_expected_decimal_projection_changed':not any(x['dm_expected_projection_differences'] for x in results),
    'normalization':'validated distinct top-level trace only; DECIMAL projection is an assertion, not cross-engine comparison normalization'},indent=2))
raise SystemExit(any(x['mysql_pre_post_differences'] or x['dm_expected_projection_differences'] for x in results))
