from datetime import datetime, timezone
from decimal import Decimal

from strats_oanda.model import (
    ClientPrice,
    HomeConversionFactors,
    OrderFillReason,
    OrderFillTransaction,
    PriceBucket,
    TradeOpen,
    parse_order_fill_transaction,
)


def test_parse_order_fill_transaction():
    data = {
        "accountBalance": "3000000.0110",
        "accountID": "101-009-31084545-001",
        "baseFinancing": "0",
        "batchID": "68",
        "commission": "0.0000",
        "financing": "0.0000",
        "fullPrice": {
            "asks": [{"liquidity": "250000", "price": "150.496"}],
            "bids": [{"liquidity": "250000", "price": "150.492"}],
            "closeoutAsk": "150.500",
            "closeoutBid": "150.488",
            "timestamp": "2025-03-26T13:50:53.182325174Z",
        },
        "fullVWAP": "150.492",
        "gainQuoteHomeConversionFactor": "1",
        "guaranteedExecutionFee": "0.0000",
        "halfSpreadCost": "0.0020",
        "homeConversionFactors": {
            "gainBaseHome": {"factor": "150.193012"},
            "gainQuoteHome": {"factor": "1"},
            "lossBaseHome": {"factor": "150.794988"},
            "lossQuoteHome": {"factor": "1"},
        },
        "id": "69",
        "instrument": "USD_JPY",
        "lossQuoteHomeConversionFactor": "1",
        "orderID": "68",
        "pl": "0.0000",
        "price": "150.492",
        "quoteGuaranteedExecutionFee": "0",
        "quotePL": "0",
        "reason": "MARKET_ORDER",
        "requestID": "79368253552993866",
        "requestedUnits": "-1",
        "time": "2025-03-26T13:50:53.280405861Z",
        "tradeOpened": {
            "guaranteedExecutionFee": "0.0000",
            "halfSpreadCost": "0.0020",
            "initialMarginRequired": "6.0198",
            "price": "150.492",
            "quoteGuaranteedExecutionFee": "0",
            "tradeID": "69",
            "units": "-1",
        },
        "type": "ORDER_FILL",
        "units": "-1",
        "userID": 31084545,
    }
    got = parse_order_fill_transaction(data)
    expect = OrderFillTransaction(
        id="69",
        time=datetime(2025, 3, 26, 13, 50, 53, 280405, tzinfo=timezone.utc),
        user_id=31084545,
        account_id="101-009-31084545-001",
        batch_id="68",
        type="ORDER_FILL",
        request_id="79368253552993866",
        order_id="68",
        client_order_id=None,
        instrument="USD_JPY",
        units=Decimal("-1"),
        home_conversion_factors=HomeConversionFactors(
            gain_quote_home={"factor": "1"},
            loss_quote_home={"factor": "1"},
            gain_base_home={"factor": "150.193012"},
            loss_base_home={"factor": "150.794988"},
        ),
        full_vwap=Decimal("150.492"),
        full_price=ClientPrice(
            type="PRICE",
            instrument=None,
            time=None,
            timestamp=datetime(2025, 3, 26, 13, 50, 53, 182325, tzinfo=timezone.utc),
            tradeable=None,
            bids=[
                PriceBucket(
                    price=Decimal("150.492"),
                    liquidity="250000",
                ),
            ],
            asks=[
                PriceBucket(
                    price=Decimal("150.496"),
                    liquidity="250000",
                ),
            ],
            closeout_bid=Decimal("150.488"),
            closeout_ask=Decimal("150.500"),
        ),
        reason=OrderFillReason.MARKET_ORDER,
        pl=Decimal("0.0000"),
        quote_pl=Decimal("0"),
        financing=Decimal("0.0000"),
        base_financing=Decimal("0"),
        quote_financing=None,
        commission=Decimal("0.0000"),
        guaranteed_execution_fee=Decimal("0.0000"),
        quote_guaranteed_execution_fee=Decimal("0"),
        account_balance=Decimal("3000000.0110"),
        trade_opened=TradeOpen(
            trade_id="69",
            units=Decimal("-1"),
            price=Decimal("150.492"),
            half_spread_cost=Decimal("0.0020"),
            initial_margin_required=Decimal("6.0198"),
            client_extensions=None,
        ),
        trades_closed=None,
        trade_reduced=None,
        half_spread_cost=Decimal("0.0020"),
    )
    assert got == expect
