"""Tests for trading engine."""

import pytest
from unittest.mock import Mock, AsyncMock, patch
from decimal import Decimal
from src.trading.engine import get_trading_engine, TradingEngine
from src.core.database import OrderSide, OrderType, OrderStatus

@pytest.mark.asyncio
class TestTradingEngine:
    
    @pytest.fixture(autouse=True)
    async def setup_data(self, db_session):
        """Setup test data."""
        from src.core.database import Exchange
        from sqlalchemy import select
        
        # Check if exchange exists
        result = await db_session.execute(select(Exchange).where(Exchange.id == 1))
        if not result.scalar_one_or_none():
            try:
                # Try enabled (new schema)
                exchange = Exchange(id=1, name="coinbase", enabled=True)
                db_session.add(exchange)
                await db_session.commit()
            except Exception:
                # Fallback if I was wrong about schema, but I checked it.
                await db_session.rollback()
                exchange = Exchange(id=1, name="coinbase")
                db_session.add(exchange)
                print("Exchange created in setup_data")
        
    async def test_execute_order_paper_trading(self, mock_exchange_adapter):
        """Test executing paper trading order."""
        engine = TradingEngine()
        
        # Mock dependencies
        engine.get_exchange_adapter = AsyncMock(return_value=mock_exchange_adapter)
        engine.risk_manager.check_order_risk = Mock(return_value=(True, ""))
        engine.paper_trading.get_balance = Mock(return_value=Decimal("10000"))
        engine.paper_trading.execute_order = Mock(return_value=True)
        # Mock logger
        engine.logger = Mock()
        
        order = await engine.execute_order(
            exchange_id=1,
            strategy_id=None,
            symbol="BTC/USD",
            side=OrderSide.BUY,
            order_type=OrderType.LIMIT,
            quantity=Decimal("0.1"),
            price=Decimal("50000"),
            paper_trading=True
        )
        
        # Check if error occurred
        if order is None:
            engine.logger.error.assert_called()
            call_args = engine.logger.error.call_args
            print(f"\nCaught exception in engine: {call_args}")
        
        assert order is not None
        assert order.symbol == "BTC/USD"
        assert order.quantity == Decimal("0.1")
        # Status might be PENDING/OPEN depending on implementation
        assert order.status in [OrderStatus.PENDING, OrderStatus.OPEN]

    async def test_execute_order_live_trading(self, mock_exchange_adapter):
        """Test executing live trading order."""
        engine = TradingEngine()
        
        # Mock dependencies
        engine.get_exchange_adapter = AsyncMock(return_value=mock_exchange_adapter)
        engine.risk_manager.check_order_risk = Mock(return_value=(True, ""))
        
        order = await engine.execute_order(
            exchange_id=1,
            strategy_id=None,
            symbol="BTC/USD",
            side=OrderSide.BUY,
            order_type=OrderType.MARKET,
            quantity=Decimal("0.1"),
            paper_trading=False
        )
        
        assert order is not None
        assert order.paper_trading is False
        mock_exchange_adapter.place_order.assert_called_once()
