"""Tests for autopilot API endpoints."""

import pytest
from unittest.mock import Mock, patch, MagicMock, AsyncMock
from fastapi.testclient import TestClient

from backend.main import app


@pytest.fixture
def client():
    """Test client fixture."""
    return TestClient(app)


@pytest.fixture
def mock_autopilot():
    """Mock autopilot instance."""
    autopilot = Mock()
    autopilot.symbol = "BTC/USD"
    autopilot.is_running = False
    autopilot.get_status.return_value = {
        "symbol": "BTC/USD",
        "running": False,
        "interval": 60.0,
        "has_market_data": True,
        "market_data_length": 100,
        "headlines_count": 5,
        "last_sentiment_score": 0.5,
        "last_pattern": "head_and_shoulders",
        "last_signal": None,
    }
    autopilot.last_signal = None
    autopilot.analyze_once.return_value = None
    return autopilot


@pytest.fixture
def mock_intelligent_autopilot():
    """Mock intelligent autopilot instance."""
    autopilot = Mock()
    autopilot.symbol = "BTC/USD"
    autopilot.is_running = False
    autopilot.enable_auto_execution = False
    autopilot.get_status.return_value = {
        "symbol": "BTC/USD",
        "timeframe": "1h",
        "running": False,
        "selected_strategy": None,
        "trades_today": 0,
        "max_trades_per_day": 10,
        "min_confidence_threshold": 0.75,
        "enable_auto_execution": False,
        "last_analysis": None,
        "model_info": {},
    }
    return autopilot


class TestUnifiedAutopilotEndpoints:
    """Tests for unified autopilot endpoints."""

    @patch('backend.api.autopilot.get_autopilot_mode_info')
    def test_get_modes(self, mock_get_mode_info, client):
        """Test getting autopilot mode information."""
        mock_get_mode_info.return_value = {
            "modes": {
                "pattern": {"name": "Pattern-Based Autopilot"},
                "intelligent": {"name": "ML-Based Autopilot"},
            },
            "comparison": {},
        }

        response = client.get("/api/autopilot/modes")
        assert response.status_code == 200
        data = response.json()
        assert "modes" in data
        assert "pattern" in data["modes"]
        assert "intelligent" in data["modes"]

    @patch('backend.api.autopilot.get_autopilot')
    @patch('backend.api.autopilot.run_autopilot_loop')
    def test_start_unified_pattern_mode(
        self, mock_run_loop, mock_get_autopilot, client, mock_autopilot
    ):
        """Test starting unified autopilot in pattern mode."""
        mock_get_autopilot.return_value = mock_autopilot

        response = client.post(
            "/api/autopilot/start-unified",
            json={
                "symbol": "BTC/USD",
                "mode": "pattern",
                "auto_execute": False,
                "interval": 60.0,
                "pattern_order": 5,
                "auto_fetch_news": True,
            },
        )

        assert response.status_code == 200
        data = response.json()
        assert data["status"] == "started"
        assert data["mode"] == "pattern"
        assert data["symbol"] == "BTC/USD"
        assert data["auto_execute"] is False
        mock_get_autopilot.assert_called_once()

    @patch('backend.api.autopilot.get_intelligent_autopilot')
    def test_start_unified_intelligent_mode(
        self, mock_get_intelligent, client, mock_intelligent_autopilot
    ):
        """Test starting unified autopilot in intelligent mode."""
        mock_get_intelligent.return_value = mock_intelligent_autopilot

        response = client.post(
            "/api/autopilot/start-unified",
            json={
                "symbol": "BTC/USD",
                "mode": "intelligent",
                "auto_execute": True,
                "exchange_id": 1,
                "timeframe": "1h",
                "interval": 60.0,
                "paper_trading": True,
            },
        )

        assert response.status_code == 200
        data = response.json()
        assert data["status"] == "started"
        assert data["mode"] == "intelligent"
        assert data["symbol"] == "BTC/USD"
        assert data["auto_execute"] is True
        assert mock_intelligent_autopilot.enable_auto_execution is True
        mock_get_intelligent.assert_called_once()

    def test_start_unified_invalid_mode(self, client):
        """Test starting unified autopilot with invalid mode."""
        response = client.post(
            "/api/autopilot/start-unified",
            json={
                "symbol": "BTC/USD",
                "mode": "invalid_mode",
                "auto_execute": False,
            },
        )

        assert response.status_code == 400
        assert "Invalid mode" in response.json()["detail"]

    @patch('backend.api.autopilot.get_autopilot')
    def test_stop_unified_pattern_mode(
        self, mock_get_autopilot, client, mock_autopilot
    ):
        """Test stopping unified autopilot in pattern mode."""
        mock_get_autopilot.return_value = mock_autopilot

        response = client.post(
            "/api/autopilot/stop-unified?symbol=BTC/USD&mode=pattern"
        )

        assert response.status_code == 200
        data = response.json()
        assert data["status"] == "stopped"
        assert data["symbol"] == "BTC/USD"
        assert data["mode"] == "pattern"
        mock_autopilot.stop.assert_called_once()

    @patch('backend.api.autopilot.get_intelligent_autopilot')
    def test_stop_unified_intelligent_mode(
        self, mock_get_intelligent, client, mock_intelligent_autopilot
    ):
        """Test stopping unified autopilot in intelligent mode."""
        mock_get_intelligent.return_value = mock_intelligent_autopilot

        response = client.post(
            "/api/autopilot/stop-unified?symbol=BTC/USD&mode=intelligent&timeframe=1h"
        )

        assert response.status_code == 200
        data = response.json()
        assert data["status"] == "stopped"
        assert data["symbol"] == "BTC/USD"
        assert data["mode"] == "intelligent"
        mock_intelligent_autopilot.stop.assert_called_once()

    def test_stop_unified_invalid_mode(self, client):
        """Test stopping unified autopilot with invalid mode."""
        response = client.post(
            "/api/autopilot/stop-unified?symbol=BTC/USD&mode=invalid_mode"
        )

        assert response.status_code == 400
        assert "Invalid mode" in response.json()["detail"]

    @patch('backend.api.autopilot.get_autopilot')
    def test_get_unified_status_pattern_mode(
        self, mock_get_autopilot, client, mock_autopilot
    ):
        """Test getting unified autopilot status in pattern mode."""
        mock_get_autopilot.return_value = mock_autopilot

        response = client.get(
            "/api/autopilot/status-unified/BTC/USD?mode=pattern"
        )

        assert response.status_code == 200
        data = response.json()
        assert data["symbol"] == "BTC/USD"
        assert data["mode"] == "pattern"
        assert "running" in data

    @patch('backend.api.autopilot.get_intelligent_autopilot')
    def test_get_unified_status_intelligent_mode(
        self, mock_get_intelligent, client, mock_intelligent_autopilot
    ):
        """Test getting unified autopilot status in intelligent mode."""
        mock_get_intelligent.return_value = mock_intelligent_autopilot

        response = client.get(
            "/api/autopilot/status-unified/BTC/USD?mode=intelligent&timeframe=1h"
        )

        assert response.status_code == 200
        data = response.json()
        assert data["symbol"] == "BTC/USD"
        assert data["mode"] == "intelligent"
        assert "running" in data

    def test_get_unified_status_invalid_mode(self, client):
        """Test getting unified autopilot status with invalid mode."""
        response = client.get(
            "/api/autopilot/status-unified/BTC/USD?mode=invalid_mode"
        )

        assert response.status_code == 400
        assert "Invalid mode" in response.json()["detail"]


class TestModeSelection:
    """Tests for mode selection logic."""

    @patch('backend.api.autopilot.get_autopilot_mode_info')
    def test_mode_info_structure(self, mock_get_mode_info):
        """Test that mode info has correct structure."""
        from src.autopilot import get_autopilot_mode_info

        mode_info = get_autopilot_mode_info()

        assert "modes" in mode_info
        assert "pattern" in mode_info["modes"]
        assert "intelligent" in mode_info["modes"]
        assert "comparison" in mode_info

        # Check pattern mode structure
        pattern = mode_info["modes"]["pattern"]
        assert "name" in pattern
        assert "description" in pattern
        assert "how_it_works" in pattern
        assert "best_for" in pattern
        assert "tradeoffs" in pattern
        assert "features" in pattern
        assert "requirements" in pattern

        # Check intelligent mode structure
        intelligent = mode_info["modes"]["intelligent"]
        assert "name" in intelligent
        assert "description" in intelligent
        assert "how_it_works" in intelligent
        assert "best_for" in intelligent
        assert "tradeoffs" in intelligent
        assert "features" in intelligent
        assert "requirements" in intelligent

        # Check comparison structure
        comparison = mode_info["comparison"]
        assert "transparency" in comparison
        assert "adaptability" in comparison
        assert "setup_time" in comparison
        assert "resource_usage" in comparison


class TestAutoExecution:
    """Tests for auto-execution functionality."""

    @patch('backend.api.autopilot.get_intelligent_autopilot')
    def test_auto_execute_enabled(
        self, mock_get_intelligent, client, mock_intelligent_autopilot
    ):
        """Test that auto-execute is set when enabled."""
        mock_get_intelligent.return_value = mock_intelligent_autopilot

        response = client.post(
            "/api/autopilot/start-unified",
            json={
                "symbol": "BTC/USD",
                "mode": "intelligent",
                "auto_execute": True,
                "exchange_id": 1,
                "timeframe": "1h",
            },
        )

        assert response.status_code == 200
        assert mock_intelligent_autopilot.enable_auto_execution is True

    @patch('backend.api.autopilot.get_intelligent_autopilot')
    def test_auto_execute_disabled(
        self, mock_get_intelligent, client, mock_intelligent_autopilot
    ):
        """Test that auto-execute is not set when disabled."""
        mock_get_intelligent.return_value = mock_intelligent_autopilot

        response = client.post(
            "/api/autopilot/start-unified",
            json={
                "symbol": "BTC/USD",
                "mode": "intelligent",
                "auto_execute": False,
                "exchange_id": 1,
                "timeframe": "1h",
            },
        )

        assert response.status_code == 200
        # Note: enable_auto_execution may have a default value, so we check it's not True
        # The actual behavior depends on the implementation


class TestBackwardCompatibility:
    """Tests for backward compatibility with old endpoints."""

    @patch('backend.api.autopilot.get_autopilot')
    @patch('backend.api.autopilot.run_autopilot_loop')
    def test_old_start_endpoint_still_works(
        self, mock_run_loop, mock_get_autopilot, client, mock_autopilot
    ):
        """Test that old /start endpoint still works (deprecated but functional)."""
        mock_get_autopilot.return_value = mock_autopilot

        response = client.post(
            "/api/autopilot/start",
            json={
                "symbol": "BTC/USD",
                "interval": 60.0,
                "pattern_order": 5,
                "auto_fetch_news": True,
            },
        )

        assert response.status_code == 200
        data = response.json()
        assert data["status"] == "started"
        assert data["symbol"] == "BTC/USD"

    @patch('backend.api.autopilot.get_intelligent_autopilot')
    def test_old_intelligent_start_endpoint_still_works(
        self, mock_get_intelligent, client, mock_intelligent_autopilot
    ):
        """Test that old /intelligent/start endpoint still works (deprecated but functional)."""
        mock_get_intelligent.return_value = mock_intelligent_autopilot

        response = client.post(
            "/api/autopilot/intelligent/start",
            json={
                "symbol": "BTC/USD",
                "exchange_id": 1,
                "timeframe": "1h",
                "interval": 60.0,
                "paper_trading": True,
            },
        )

        assert response.status_code == 200
        data = response.json()
        assert data["status"] == "started"
        assert data["symbol"] == "BTC/USD"

