"""Compare five fictional CRM currency imports using exact decimal arithmetic."""

import json
from dataclasses import asdict, dataclass, replace
from decimal import Decimal, ROUND_HALF_UP


@dataclass(frozen=True)
class Deal:
    id: str
    stage: str
    amount: str
    currency: str
    close_date: str
    usd_per_unit: str

    @property
    def usd(self):
        value = Decimal(self.amount) * Decimal(self.usd_per_unit)
        return value.quantize(Decimal("0.01"), rounding=ROUND_HALF_UP)


eur = Deal("A", "open", "10000", "EUR", "2026-12-15", "1.10")
gbp = Deal("B", "open", "8000", "GBP", "2026-12-18", "1.25")
won = Deal("C", "closed won", "5000", "EUR", "2026-06-30", "1.08")
source = (eur, gbp, won)

scenarios = {
    "unchanged": source,
    "offsetting_errors": (
        replace(eur, currency="USD", usd_per_unit="1"),
        replace(gbp, usd_per_unit="1.375"),
        won,
    ),
    "converted_amount_imported_as_native": (
        replace(eur, amount="11000", currency="USD", usd_per_unit="1"), gbp, won,
    ),
    "changed_close_date_and_rate": (
        eur, gbp, replace(won, close_date="2026-07-01", usd_per_unit="1.10"),
    ),
    "reciprocal_rate": (eur, replace(gbp, usd_per_unit="0.80"), won),
}


def total(rows):
    return sum(deal.usd for deal in rows)


def reconcile(destination):
    records = {deal.id: deal for deal in destination}
    assert len(records) == len(destination) and records.keys() == {deal.id for deal in source}
    differences = {}
    for expected in source:
        actual = records[expected.id]
        expected_fields = asdict(expected)
        actual_fields = asdict(actual)
        changed = [field for field in expected_fields if expected_fields[field] != actual_fields[field]]
        if changed:
            differences[expected.id] = {
                "changed_fields": changed,
                "usd_difference": str(actual.usd - expected.usd),
            }
    return {
        "destination": [asdict(deal) for deal in destination],
        "usd_total": str(total(destination)),
        "usd_difference": str(total(destination) - total(source)),
        "rows_with_changes": differences,
    }


if __name__ == "__main__":
    print(json.dumps({
        "reporting_currency": "USD",
        "source": [asdict(deal) for deal in source],
        "source_usd_total": str(total(source)),
        "scenarios": {name: reconcile(deals) for name, deals in scenarios.items()},
    }, indent=2))
