"""Tests for SilicoBot client."""
import pytest
from unittest.mock import Mock, patch
from silico.client import SilicoBot
from silico.exceptions import AuthenticationError, RateLimitError


def test_client_creation_with_api_key():
    """Client should accept API key."""
    bot = SilicoBot(api_key="sk_test_123")
    assert bot.api_key == "sk_test_123"


def test_client_detects_localhost():
    """Client should auto-detect localhost for development."""
    with patch("socket.socket") as mock_socket:
        # Mock localhost:8000 is reachable
        mock_socket.return_value.connect_ex.return_value = 0

        bot = SilicoBot(api_key="sk_test")
        assert "localhost" in bot.base_url


def test_client_uses_production_when_localhost_unavailable():
    """Client should use production when localhost is down."""
    with patch("socket.socket") as mock_socket:
        # Mock localhost is NOT reachable
        mock_socket.return_value.connect_ex.return_value = 1

        bot = SilicoBot(api_key="sk_test")
        assert "silico.fun" in bot.base_url or "api.silico" in bot.base_url


def test_client_accepts_explicit_base_url():
    """Client should accept explicit base_url override."""
    bot = SilicoBot(
        api_key="sk_test",
        base_url="http://custom:9000"
    )
    assert bot.base_url == "http://custom:9000"


@patch("requests.Session.request")
def test_execute_trade_success(mock_request):
    """Client should execute trades successfully."""
    mock_request.return_value.status_code = 200
    mock_request.return_value.json.return_value = {
        "success": True,
        "data": {
            "trade_id": "123",
            "executed_price": 100.5
        }
    }

    bot = SilicoBot(api_key="sk_test")
    result = bot.buy("SOL/USDC", amount_usdc=100)

    assert result.success is True
    assert result.trade_id == "123"

    # Verify API was called correctly
    mock_request.assert_called_once()
    args, kwargs = mock_request.call_args
    assert kwargs["method"] == "POST"
    assert "/api/trade/execute" in kwargs["url"]


@patch("requests.Session.request")
def test_execute_trade_auth_error(mock_request):
    """Client should raise AuthenticationError on 401."""
    mock_request.return_value.status_code = 401
    mock_request.return_value.json.return_value = {
        "success": False,
        "detail": "Invalid API key"
    }

    bot = SilicoBot(api_key="sk_invalid")

    with pytest.raises(AuthenticationError):
        bot.buy("SOL/USDC", amount_usdc=100)


@patch("requests.Session.request")
def test_execute_trade_rate_limit(mock_request):
    """Client should raise RateLimitError on 429."""
    mock_request.return_value.status_code = 429
    mock_request.return_value.json.return_value = {
        "success": False,
        "detail": {
            "error": "Rate limit exceeded",
            "retry_after_seconds": 30
        }
    }

    bot = SilicoBot(api_key="sk_test")

    with pytest.raises(RateLimitError) as exc_info:
        bot.buy("SOL/USDC", amount_usdc=100)

    assert exc_info.value.retry_after == 30


@patch("requests.Session.request")
def test_get_price(mock_request):
    """Client should fetch market prices."""
    mock_request.return_value.status_code = 200
    mock_request.return_value.json.return_value = {
        "success": True,
        "data": {
            "price": 100.5
        }
    }

    bot = SilicoBot(api_key="sk_test")
    price = bot.get_price("SOL/USDC")

    assert price == 100.5
