"""Tests for slippage model."""

import pytest
from decimal import Decimal
from src.backtesting.slippage import SlippageModel, FeeModel


class TestSlippageModel:
    """Tests for SlippageModel."""
    
    @pytest.fixture
    def slippage_model(self):
        """Create slippage model."""
        return SlippageModel(slippage_rate=0.001)
    
    def test_calculate_fill_price_market_buy(self, slippage_model):
        """Test fill price calculation for market buy."""
        order_price = Decimal('50000.0')
        market_price = Decimal('50000.0')
        
        fill_price = slippage_model.calculate_fill_price(
            order_price, "buy", "market", market_price
        )
        
        assert fill_price > market_price  # Buy orders pay more
    
    def test_calculate_fill_price_market_sell(self, slippage_model):
        """Test fill price calculation for market sell."""
        order_price = Decimal('50000.0')
        market_price = Decimal('50000.0')
        
        fill_price = slippage_model.calculate_fill_price(
            order_price, "sell", "market", market_price
        )
        
        assert fill_price < market_price  # Sell orders receive less
    
    def test_calculate_fill_price_limit(self, slippage_model):
        """Test fill price for limit orders."""
        order_price = Decimal('49000.0')
        market_price = Decimal('50000.0')
        
        fill_price = slippage_model.calculate_fill_price(
            order_price, "buy", "limit", market_price
        )
        
        assert fill_price == order_price  # Limit orders fill at order price


class TestFeeModel:
    """Tests for FeeModel."""
    
    @pytest.fixture
    def fee_model(self):
        """Create fee model."""
        return FeeModel(maker_fee=0.001, taker_fee=0.002)
    
    def test_calculate_fee_maker(self, fee_model):
        """Test maker fee calculation."""
        fee = fee_model.calculate_fee(
            quantity=Decimal('0.01'),
            price=Decimal('50000.0'),
            is_maker=True
        )
        
        assert fee > 0
        # Fee should be 0.1% of trade value
        expected = Decimal('0.01') * Decimal('50000.0') * Decimal('0.001')
        assert abs(float(fee - expected)) < 0.01
    
    def test_calculate_fee_taker(self, fee_model):
        """Test taker fee calculation."""
        fee = fee_model.calculate_fee(
            quantity=Decimal('0.01'),
            price=Decimal('50000.0'),
            is_maker=False
        )
        
        assert fee > 0
        # Taker fee should be higher than maker
        maker_fee = fee_model.calculate_fee(
            Decimal('0.01'), Decimal('50000.0'), is_maker=True
        )
        assert fee > maker_fee

