"""投影一致性校验：stock_qty 必须始终等于账本重算结果。"""
from decimal import Decimal

Key = tuple[int, int]  # (product_id, variant_id)，variant_id=0 表示无规格


def find_drift(ledger: dict[Key, Decimal],
               projected: dict[Key, Decimal]) -> list[tuple[Key, Decimal, Decimal]]:
    """返回 [(key, 账本值, 投影值)]，空列表表示一致。"""
    drift = []
    for key in set(ledger) | set(projected):
        a = ledger.get(key, Decimal("0"))
        b = projected.get(key, Decimal("0"))
        if a != b:
            drift.append((key, a, b))
    return sorted(drift)


async def reconcile_inventory(db, tenant_id: int) -> list[dict]:
    """Compare append-only ledger totals to materialized balance rows by exact dimension."""
    from sqlalchemy import text

    ledger_rows = (await db.execute(
        text("SELECT product_id,COALESCE(variant_id,0),warehouse_id,COALESCE(location_id,0),"
             "COALESCE(batch_id,0),stock_state,SUM(qty_delta) FROM inventory_transactions "
             "WHERE tenant_id=:tid GROUP BY product_id,COALESCE(variant_id,0),warehouse_id,"
             "COALESCE(location_id,0),COALESCE(batch_id,0),stock_state"),
        {"tid": tenant_id},
    )).fetchall()
    balance_rows = (await db.execute(
        text("SELECT product_id,variant_id,warehouse_id,location_id,batch_id,stock_state,SUM(qty) "
             "FROM inventory_balances WHERE tenant_id=:tid "
             "GROUP BY product_id,variant_id,warehouse_id,location_id,batch_id,stock_state"),
        {"tid": tenant_id},
    )).fetchall()
    ledger = {tuple(row[:6]): Decimal(str(row[6] or 0)) for row in ledger_rows}
    balances = {tuple(row[:6]): Decimal(str(row[6] or 0)) for row in balance_rows}
    differences = []
    for key in sorted(set(ledger) | set(balances), key=lambda value: tuple(str(x) for x in value)):
        ledger_qty = ledger.get(key, Decimal("0"))
        balance_qty = balances.get(key, Decimal("0"))
        if ledger_qty != balance_qty:
            differences.append({
                "product_id": key[0], "variant_id": key[1] or None, "warehouse_id": key[2],
                "location_id": key[3] or None, "batch_id": key[4] or None, "stock_state": key[5],
                "ledger_qty": str(ledger_qty), "balance_qty": str(balance_qty),
                "difference": str(balance_qty - ledger_qty),
            })
    return differences
