import json
from pathlib import Path

root = Path(__file__).parent
read = lambda n: json.loads((root / f"{n}.json").read_text())
rb, rc, gb, gc, cb, cc = [read(n) for n in ("red-B", "red-C", "green-B", "green-C", "client-B", "client-C")]
fields = ["total_price", "ori_total_price", "order_price", "pay_price", "cash", "subsidy", "gift",
          "activity_principal_payment", "withdrawable_cash_payment", "booking_unit_price", "package_fee",
          "refund_amount", "cash_refund_amount", "subsidy_refund_amount", "gift_refund_amount",
          "activity_principal_refund_amount", "withdrawable_cash_refund_amount", "remain_balance",
          "remain_cash", "remain_subsidy", "remain_gift", "management_fee", "discount_amount", "actual_strategy_value"]
goods_fields = ["dishes_weight", "dishes_price", "total_price"]
for lane in (rb, rc):
    for table, whitelist in (("meal_order", fields), ("initial_menu", goods_fields)):
        schema = {c["column_name"].lower(): c for c in lane["schema"][table]}
        for field in whitelist:
            c = schema[field]
            assert c["data_type"].lower() == "decimal"
            assert (int(c["precision_value"]), int(c["scale_value"])) == (10, 2)
for field in fields:
    assert rb["routes"]["order_detail"]["shape"]["data"][field] == "string"
    assert rc["routes"]["order_detail"]["shape"]["data"][field] == "number"
    assert gc["routes"]["order_detail"]["shape"]["data"][field] == "string"
for field in goods_fields:
    assert rc["routes"]["order_detail"]["shape"]["data"]["goods"][0][field] == "number"
    assert gc["routes"]["order_detail"]["shape"]["data"]["goods"][0][field] == "string"

# Same eight initial camel-path requests before/after, not cross-path comparisons.
assert len(rb["routes"]) == len(gb["routes"]) == 8
for name, before in rb["routes"].items():
    after = gb["routes"][name]
    assert before["path"] == after["path"]
    assert before["method"] == after["method"]
    assert before["wire_response_sha256"] == after["wire_response_sha256"], name
for result in (gb, gc, cb, cc):
    assert result["failure"] == "" and result["source_unchanged"]
    assert result["database_writes"] == 0 and result["original_debug"] is False
# Each batch's before/after is stable; B cross-phase source digests differ and remain open.
b_cross_phase_difference = len({rb["source_before"], gb["source_before"], cb["source_before"]}) > 1
assert rc["source_before"] == gc["source_before"] == cc["source_before"]
for result in (gb, gc):
    assert result["routes"]["order_list"]["rows"] > 0
    assert result["routes"]["order_list"]["source_match"]
    assert result["routes"]["order_list"]["ordered_desc"]
    assert result["routes"]["order_detail"]["verified_root_decimals"] == 24
    assert result["routes"]["order_detail"]["goods_source_match"]
assert gb["routes"]["order_list"]["selected_order_wire_shape"] == gc["routes"]["order_list"]["selected_order_wire_shape"]
b_detail = gb["routes"]["order_detail"]["wire_shape"]["fields"]["data"]["fields"]
c_detail = gc["routes"]["order_detail"]["wire_shape"]["fields"]["data"]["fields"]
assert set(b_detail) - set(c_detail) == {"bank_user_name"}
assert set(c_detail) - set(b_detail) == set()
assert {k: v for k, v in b_detail.items() if k != "bank_user_name"} == c_detail

# Four additional live-client snake-path requests: never count camel aliases twice.
names = {"restaurant_list", "restaurant_detail", "restaurant_options", "stall_options"}
assert set(cb["routes"]) == set(cc["routes"]) == names
for name in names:
    b, c = cb["routes"][name], cc["routes"][name]
    assert b["path"].startswith("/api/dining_config/") and b["path"] == c["path"]
    assert b["method"] == c["method"] == "POST"
    assert b["status"] == c["status"] == 200 and b["code"] == c["code"] == 0
    assert b["source_match"] and c["source_match"]
    assert b["wire_shape"] == c["wire_shape"], name
print(json.dumps({"unique_method_keys": 6, "partial_compatible_keys": 5,
                  "explicit_contract_failure_keys": 1,
                  "open_schema_field": "bank_user_name",
                  "initial_camel_scenarios_per_engine": 8,
                  "client_snake_scenarios_per_engine": 4,
                  "mysql_same_path_wire_bodies_unchanged": 8,
                  "root_decimal_types_fixed": 24, "goods_decimal_types_fixed": 3,
                  "b_cross_phase_source_digest_difference_open": b_cross_phase_difference,
                  "cross_database_full_values_equal_claimed": False,
                  "aliases_counted_as_extra_interfaces": False}))
