import pytest
from unittest.mock import MagicMock, patch
import sys
from app.services.routing_optimizer import RoutingOptimizer

# Mock OR-Tools if not installed in the test environment
try:
    from ortools.constraint_solver import routing_enums_pb2
    from ortools.constraint_solver import pywrapcp
    HAS_ORTOOLS = True
except ImportError:
    HAS_ORTOOLS = False

@pytest.mark.asyncio
async def test_routing_optimizer_initialization():
    optimizer = RoutingOptimizer()
    assert optimizer.has_ortools == HAS_ORTOOLS

@pytest.mark.asyncio
async def test_optimize_daily_routes_fallback():
    # Force fallback by mocking has_ortools to False
    optimizer = RoutingOptimizer()
    optimizer.has_ortools = False
    
    depot_location = (40.7128, -74.0060) # NYC
    deliveries = [
        {
            'id': 'd1',
            'location': (40.730610, -73.935242), # Brooklyn
            'weight_kg': 100
        },
        {
            'id': 'd2',
            'location': (40.758896, -73.985130), # Times Square
            'weight_kg': 50
        }
    ]
    
    result = await optimizer.optimize_daily_routes(deliveries, depot_location)
    
    assert result['status'] == 'success'
    assert result['algorithm_used'] == 'fallback_sequential'
    assert len(result['routes']) == 1
    assert len(result['routes'][0]['stops']) == 4 # Start + 2 deliveries + End

@pytest.mark.asyncio
async def test_optimize_daily_routes_vrp():
    if not HAS_ORTOOLS:
        pytest.skip("OR-Tools not installed")
        
    optimizer = RoutingOptimizer()
    
    depot_location = (40.7128, -74.0060) # NYC
    deliveries = [
        {
            'id': 'd1',
            'location': (40.730610, -73.935242), # Brooklyn
            'weight_kg': 100
        },
        {
            'id': 'd2',
            'location': (40.758896, -73.985130), # Times Square
            'weight_kg': 50
        },
        {
            'id': 'd3',
            'location': (40.7829, -73.9654), # Central Park
            'weight_kg': 200
        }
    ]
    
    # Run optimization
    result = await optimizer.optimize_daily_routes(deliveries, depot_location)
    
    assert result['status'] == 'success'
    assert result['algorithm_used'] == 'ortools_vrp'
    assert len(result['routes']) >= 1
    
    # Check if all deliveries are covered
    delivery_ids = []
    for route in result['routes']:
        for stop in route['stops']:
            if 'delivery_id' in stop and not stop.get('location') == 'depot':
                delivery_ids.append(stop['delivery_id'])
                
    assert 'd1' in delivery_ids
    assert 'd2' in delivery_ids
    assert 'd3' in delivery_ids
