"""Strategy API endpoints."""

from typing import List
from fastapi import APIRouter, HTTPException, Depends
from sqlalchemy import select

from ..core.dependencies import get_strategy_registry
from ..core.schemas import (
    StrategyCreate, StrategyUpdate, StrategyResponse
)
from src.core.database import Strategy, get_database
from src.strategies.scheduler import get_scheduler as _get_scheduler

def get_strategy_scheduler():
    """Get strategy scheduler instance."""
    return _get_scheduler()

router = APIRouter()


@router.get("/", response_model=List[StrategyResponse])
async def list_strategies():
    """List all strategies."""
    try:
        db = get_database()
        async with db.get_session() as session:
            stmt = select(Strategy).order_by(Strategy.created_at.desc())
            result = await session.execute(stmt)
            strategies = result.scalars().all()
            return [StrategyResponse.model_validate(s) for s in strategies]
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))


@router.get("/available")
async def list_available_strategies(
    registry=Depends(get_strategy_registry)
):
    """List available strategy types."""
    try:
        return {"strategies": registry.list_available()}
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))


@router.post("/", response_model=StrategyResponse)
async def create_strategy(strategy_data: StrategyCreate):
    """Create a new strategy."""
    try:
        db = get_database()
        async with db.get_session() as session:
            strategy = Strategy(
                name=strategy_data.name,
                description=strategy_data.description,
                strategy_type=strategy_data.strategy_type,
                class_name=strategy_data.class_name,
                parameters=strategy_data.parameters,
                timeframes=strategy_data.timeframes,
                paper_trading=strategy_data.paper_trading,
                schedule=strategy_data.schedule,
                enabled=False
            )
            session.add(strategy)
            await session.commit()
            await session.refresh(strategy)
            return StrategyResponse.model_validate(strategy)
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))


@router.get("/{strategy_id}", response_model=StrategyResponse)
async def get_strategy(strategy_id: int):
    """Get strategy by ID."""
    try:
        db = get_database()
        async with db.get_session() as session:
            stmt = select(Strategy).where(Strategy.id == strategy_id)
            result = await session.execute(stmt)
            strategy = result.scalar_one_or_none()
            if not strategy:
                raise HTTPException(status_code=404, detail="Strategy not found")
            return StrategyResponse.model_validate(strategy)
    except HTTPException:
        raise
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))


@router.put("/{strategy_id}", response_model=StrategyResponse)
async def update_strategy(strategy_id: int, strategy_data: StrategyUpdate):
    """Update a strategy."""
    try:
        db = get_database()
        async with db.get_session() as session:
            stmt = select(Strategy).where(Strategy.id == strategy_id)
            result = await session.execute(stmt)
            strategy = result.scalar_one_or_none()
            if not strategy:
                raise HTTPException(status_code=404, detail="Strategy not found")
            
            if strategy_data.name is not None:
                strategy.name = strategy_data.name
            if strategy_data.description is not None:
                strategy.description = strategy_data.description
            if strategy_data.parameters is not None:
                strategy.parameters = strategy_data.parameters
            if strategy_data.timeframes is not None:
                strategy.timeframes = strategy_data.timeframes
            if strategy_data.enabled is not None:
                strategy.enabled = strategy_data.enabled
            if strategy_data.schedule is not None:
                strategy.schedule = strategy_data.schedule
            
            await session.commit()
            await session.refresh(strategy)
            return StrategyResponse.model_validate(strategy)
    except HTTPException:
        raise
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))


@router.delete("/{strategy_id}")
async def delete_strategy(strategy_id: int):
    """Delete a strategy."""
    try:
        db = get_database()
        async with db.get_session() as session:
            stmt = select(Strategy).where(Strategy.id == strategy_id)
            result = await session.execute(stmt)
            strategy = result.scalar_one_or_none()
            if not strategy:
                raise HTTPException(status_code=404, detail="Strategy not found")
            
            await session.delete(strategy)
            await session.commit()
            return {"status": "deleted", "strategy_id": strategy_id}
    except HTTPException:
        raise
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))


@router.post("/{strategy_id}/start")
async def start_strategy(strategy_id: int):
    """Start a strategy manually (bypasses Autopilot)."""
    try:
        db = get_database()
        async with db.get_session() as session:
            stmt = select(Strategy).where(Strategy.id == strategy_id)
            result = await session.execute(stmt)
            strategy = result.scalar_one_or_none()
            if not strategy:
                raise HTTPException(status_code=404, detail="Strategy not found")
            
            # Start strategy via scheduler
            scheduler = get_strategy_scheduler()
            scheduler.start_strategy(strategy_id)
            
            strategy.running = True  # Only set running, not enabled
            await session.commit()
            
            return {"status": "started", "strategy_id": strategy_id}
    except HTTPException:
        raise
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))


@router.post("/{strategy_id}/stop")
async def stop_strategy(strategy_id: int):
    """Stop a manually running strategy."""
    try:
        db = get_database()
        async with db.get_session() as session:
            stmt = select(Strategy).where(Strategy.id == strategy_id)
            result = await session.execute(stmt)
            strategy = result.scalar_one_or_none()
            if not strategy:
                raise HTTPException(status_code=404, detail="Strategy not found")
            
            # Stop strategy via scheduler
            scheduler = get_strategy_scheduler()
            scheduler.stop_strategy(strategy_id)
            
            strategy.running = False  # Only set running, not enabled
            await session.commit()
            
            return {"status": "stopped", "strategy_id": strategy_id}
    except HTTPException:
        raise
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))


@router.post("/{strategy_type}/optimize")
async def optimize_strategy(
    strategy_type: str,
    symbol: str = "BTC/USD",
    method: str = "genetic",
    population_size: int = 50,
    generations: int = 100
):
    """Optimize strategy parameters using genetic algorithm.
    
    This endpoint queues an optimization task and returns immediately.
    Use /api/tasks/{task_id} to monitor progress.
    
    Args:
        strategy_type: Type of strategy to optimize (e.g., 'rsi', 'macd')
        symbol: Trading symbol for backtesting
        method: Optimization method ('genetic', 'grid')
        population_size: Population size for genetic algorithm
        generations: Number of generations
        
    Returns:
        Task ID for monitoring
    """
    try:
        from src.worker.tasks import optimize_strategy_task
        
        # Get parameter ranges for the strategy type
        registry = get_strategy_registry()
        strategy_class = registry.get(strategy_type)
        
        if not strategy_class:
            raise HTTPException(status_code=404, detail=f"Strategy type '{strategy_type}' not found")
        
        # Default parameter ranges based on strategy type
        param_ranges = {
            "rsi": {"period": (5, 50), "overbought": (60, 90), "oversold": (10, 40)},
            "macd": {"fast_period": (5, 20), "slow_period": (15, 40), "signal_period": (5, 15)},
            "moving_average": {"short_period": (5, 30), "long_period": (20, 100)},
            "bollinger_mean_reversion": {"period": (10, 50), "std_dev": (1.5, 3.0)},
        }.get(strategy_type.lower(), {"period": (10, 50)})
        
        # Queue the optimization task
        task = optimize_strategy_task.delay(
            strategy_type=strategy_type,
            symbol=symbol,
            param_ranges=param_ranges,
            method=method,
            population_size=population_size,
            generations=generations
        )
        
        return {
            "task_id": task.id,
            "status": "queued",
            "strategy_type": strategy_type,
            "symbol": symbol,
            "method": method
        }
        
    except HTTPException:
        raise
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))


@router.get("/{strategy_id}/status")
async def get_strategy_status(strategy_id: int):
    """Get real-time status of a running strategy.
    
    Returns execution info including last tick time, last signal, and stats.
    """
    try:
        scheduler = get_strategy_scheduler()
        status = scheduler.get_strategy_status(strategy_id)
        
        if not status:
            # Check if strategy exists but isn't running
            db = get_database()
            async with db.get_session() as session:
                stmt = select(Strategy).where(Strategy.id == strategy_id)
                result = await session.execute(stmt)
                strategy = result.scalar_one_or_none()
                
                if not strategy:
                    raise HTTPException(status_code=404, detail="Strategy not found")
                
                return {
                    "strategy_id": strategy_id,
                    "name": strategy.name,
                    "type": strategy.strategy_type,
                    "symbol": strategy.parameters.get('symbol') if strategy.parameters else None,
                    "running": False,
                    "enabled": strategy.enabled,
                }
        
        return status
        
    except HTTPException:
        raise
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))


@router.get("/running/all")
async def get_all_running_strategies():
    """Get status of all currently running strategies."""
    try:
        scheduler = get_strategy_scheduler()
        active = scheduler.get_all_active_strategies()
        return {
            "total_running": len(active),
            "strategies": active
        }
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))
