"""Synthetic accounting fixture. Standard library only; no broker or market data."""
from decimal import Decimal as D


class Ledger:
    def __init__(self):
        self.fills = {}
        self.fees = {}

    def fill(self, execution_id, signed_quantity, price):
        record = (D(signed_quantity), D(price))
        if execution_id in self.fills and self.fills[execution_id] != record:
            raise ValueError("Execution correction needs explicit reconciliation")
        self.fills[execution_id] = record

    def fee(self, execution_id, amount, currency, *, correction=False):
        record = (D(amount), currency)
        if execution_id in self.fees and self.fees[execution_id] != record and not correction:
            raise ValueError("Conflicting fee requires explicit correction")
        self.fees[execution_id] = record

    def closed_pnl(self, usd_per_unit):
        if not self.fills or sum(q for q, _ in self.fills.values()) != 0:
            raise ValueError("Fixture supports a closed single-instrument round trip only")
        if self.fills.keys() != self.fees.keys():
            raise ValueError("Unmatched execution or pending fee")
        cash = -sum(q * p for q, p in self.fills.values())
        for amount, currency in self.fees.values():
            if currency not in usd_per_unit or D(usd_per_unit[currency]) <= 0:
                raise ValueError("Missing or invalid FX rate")
            cash -= amount * D(usd_per_unit[currency])
        return cash


def expect_error(action):
    try:
        action()
    except ValueError:
        return
    raise AssertionError("Expected unresolved input to fail")


def main():
    rates = {"USD": "1"}
    actual = Ledger()
    actual.fee("buy", "1", "USD")
    actual.fill("buy", "100", "100.02")
    actual.fill("sell", "-100", "100.98")
    expect_error(lambda: actual.closed_pnl(rates))
    actual.fee("sell", "1", "USD")
    assert actual.closed_pnl(rates) == D("94")
    actual.fill("buy", "100", "100.02")
    actual.fee("sell", "1", "USD")
    assert actual.closed_pnl(rates) == D("94")
    expect_error(lambda: actual.fee("sell", "1.50", "USD"))
    actual.fee("sell", "1.50", "USD", correction=True)
    assert actual.closed_pnl(rates) == D("93.50")
    actual.fee("sell", "7.80", "HKD", correction=True)
    expect_error(lambda: actual.closed_pnl(rates))
    assert actual.closed_pnl({**rates, "HKD": D(1) / D("7.8")}) == D("94")
    replay = Ledger()
    replay.fill("buy", "100", "100")
    replay.fill("sell", "-100", "101")
    replay.fee("buy", "1", "USD")
    replay.fee("sell", "1", "USD")
    assert replay.closed_pnl(rates) == D("98")
    print("PASS: synthetic cost reconciliation; replay=98 USD, actual=94 USD")


if __name__ == "__main__":
    main()
