import pytest
from pandas.tseries.offsets import BDay

from wbportfolio.models import Order


@pytest.mark.django_db
class TestHandleTradeImport:
    def test_skips_cash_trades(self, trade_factory, order_factory, instrument_factory):
        """Ignores cash trades entirely."""
        cash_instrument = instrument_factory.create(is_cash=True)
        order = order_factory.create(underlying_instrument=cash_instrument)
        cash_trade = trade_factory.create(
            underlying_instrument=cash_instrument,
            transaction_date=(order.value_date + BDay(1)).date(),
            portfolio=order.portfolio,
        )  # this is theorically invalid, but it is just for testing purpose

        Order.handle_trade_import(cash_trade)
        order.refresh_from_db()

        assert order.execution_trade is None
        # No changes expected

    def test_skips_customer_trades(self, customer_trade_factory, order_factory):
        """Ignores customer trades."""

        order = order_factory.create()
        customer_trade = customer_trade_factory.create(
            underlying_instrument=order.underlying_instrument,
            transaction_date=(order.value_date + BDay(1)).date(),
            portfolio=order.portfolio,
        )  # this is theorically invalid, but it is just for testing purpose

        Order.handle_trade_import(customer_trade)
        # No changes expected
        assert order.execution_trade is None

    def test_links_to_exact_instrument_match(self, trade_factory, order_factory):
        """Links to earliest order with exact instrument match."""
        order = order_factory.create()
        trade = trade_factory.create(
            underlying_instrument=order.underlying_instrument,
            transaction_date=(order.value_date + BDay(4)).date(),
            portfolio=order.portfolio,
        )

        Order.handle_trade_import(trade, bday_window=2)
        order.refresh_from_db()
        assert order.execution_trade is None

        Order.handle_trade_import(trade, bday_window=3)
        order.refresh_from_db()
        assert order.execution_trade == trade
        assert order.execution_status == Order.ExecutionStatus.EXECUTED

    def test_links_to_parent_instrument_match(self, trade_factory, order_factory, instrument_factory):
        """Links via parent instrument hierarchy."""
        parent = instrument_factory.create()
        child1 = instrument_factory.create(parent=parent)
        child2 = instrument_factory.create(parent=parent)

        order = order_factory.create(
            underlying_instrument=child2,  # Parent match
        )
        trade = trade_factory.create(
            transaction_date=(order.value_date + BDay(1)).date(),
            portfolio=order.portfolio,
            underlying_instrument=child1,
        )

        Order.handle_trade_import(trade)
        order.refresh_from_db()
        assert order.execution_trade == trade

    def test_update_earlier_execution(self, trade_factory, order_factory):
        """Doesn't overwrite earlier execution_trade."""

        order = order_factory.create()

        trade = trade_factory.create(
            transaction_date=(order.value_date + BDay(2)).date(),
            portfolio=order.portfolio,
            underlying_instrument=order.underlying_instrument,
        )
        Order.handle_trade_import(trade)
        order.refresh_from_db()
        assert order.execution_trade == trade  # Unchanged

        earlier_trade = trade_factory.create(
            transaction_date=(order.value_date + BDay(1)).date(),
            portfolio=order.portfolio,
            underlying_instrument=order.underlying_instrument,
        )
        Order.handle_trade_import(earlier_trade)
        order.refresh_from_db()
        assert order.execution_trade == earlier_trade  # Unchanged
