"""Tests for data models."""
import pytest
from silico.models import TradeRequest, TradeResponse, MarketData


def test_trade_request_creation():
    """Trade request should validate required fields."""
    req = TradeRequest(
        symbol="SOL/USDC",
        side="BUY",
        amount_usdc=100.0
    )
    assert req.symbol == "SOL/USDC"
    assert req.side == "BUY"
    assert req.amount_usdc == 100.0
    assert req.max_slippage_bps == 50  # default


def test_trade_request_with_optional_fields():
    """Trade request should accept optional fields."""
    req = TradeRequest(
        symbol="SOL/USDC",
        side="SELL",
        amount_usdc=50.0,
        strategy_tag="SCALPING",
        max_slippage_bps=100,
        natural_language_intent="Taking profit"
    )
    assert req.strategy_tag == "SCALPING"
    assert req.max_slippage_bps == 100
    assert req.natural_language_intent == "Taking profit"


def test_trade_request_to_dict():
    """Trade request should serialize to API format."""
    req = TradeRequest(
        symbol="SOL/USDC",
        side="BUY",
        amount_usdc=100.0
    )
    data = req.to_dict()
    assert data["symbol"] == "SOL/USDC"
    assert data["side"] == "BUY"
    assert data["amount_usdc"] == 100.0


def test_trade_request_invalid_side():
    """Trade request should reject invalid sides."""
    with pytest.raises(ValueError, match="side must be BUY or SELL"):
        TradeRequest(
            symbol="SOL/USDC",
            side="INVALID",
            amount_usdc=100.0
        )


def test_trade_request_negative_amount():
    """Trade request should reject negative amounts."""
    with pytest.raises(ValueError, match="amount_usdc must be positive"):
        TradeRequest(
            symbol="SOL/USDC",
            side="BUY",
            amount_usdc=-10.0
        )


def test_trade_response_success():
    """Trade response should parse successful trades."""
    response = TradeResponse.from_api_response({
        "success": True,
        "data": {
            "trade_id": "123",
            "symbol": "SOL/USDC",
            "side": "BUY",
            "amount_usdc": 100.0,
            "executed_price": 100.5,
            "amount_received": 0.995,
            "slippage_bps": 25,
            "status": "EXECUTED"
        }
    })
    assert response.success is True
    assert response.trade_id == "123"
    assert response.executed_price == 100.5


def test_trade_response_failure():
    """Trade response should parse failed trades."""
    response = TradeResponse.from_api_response({
        "success": False,
        "detail": "Insufficient balance"
    })
    assert response.success is False
    assert response.error_message == "Insufficient balance"


def test_market_data_creation():
    """Market data should store price quotes."""
    market = MarketData()
    market.update_price("SOL/USDC", 100.5)

    assert market.get_price("SOL/USDC") == 100.5


def test_market_data_missing_symbol():
    """Market data should return None for unknown symbols."""
    market = MarketData()
    assert market.get_price("UNKNOWN/USDC") is None
