"""AutoPilot API endpoints."""

from typing import Dict, Any, Optional, List
from fastapi import APIRouter, HTTPException, BackgroundTasks
from pydantic import BaseModel

from ..core.dependencies import get_database
from ..core.schemas import OrderSide
from src.core.database import get_database as get_db
# Import autopilot - path should be set up in main.py
from src.autopilot import (
    stop_all_autopilots,
    get_intelligent_autopilot,
    get_strategy_selector,
    get_performance_tracker,
    get_performance_tracker,
    get_autopilot_mode_info,
)
from src.worker.tasks import train_model_task
from src.core.config import get_config
from celery.result import AsyncResult

router = APIRouter()





class BootstrapConfig(BaseModel):
    """Bootstrap training data configuration."""
    days: int = 90
    timeframe: str = "1h"
    min_samples_per_strategy: int = 10
    symbols: List[str] = ["BTC/USD", "ETH/USD"]


class MultiSymbolAutopilotConfig(BaseModel):
    """Multi-symbol autopilot configuration."""
    symbols: List[str]
    mode: str = "intelligent"
    auto_execute: bool = False
    timeframe: str = "1h"
    exchange_id: int = 1
    paper_trading: bool = True
    interval: float = 60.0






# =============================================================================
# Intelligent Autopilot Endpoints
# =============================================================================

class IntelligentAutopilotConfig(BaseModel):
    symbol: str
    exchange_id: int = 1
    timeframe: str = "1h"
    interval: float = 60.0
    paper_trading: bool = True


# =============================================================================
# Unified Autopilot Endpoints
# =============================================================================

class UnifiedAutopilotConfig(BaseModel):
    """Unified autopilot configuration (Inteligent Mode)."""
    symbol: str
    mode: str = "intelligent"  # Kept for compatibility but only "intelligent" is supported
    auto_execute: bool = False
    interval: float = 60.0
    exchange_id: int = 1
    timeframe: str = "1h"
    paper_trading: bool = True


@router.post("/intelligent/start", deprecated=True)
async def start_intelligent_autopilot(
    config: IntelligentAutopilotConfig,
    background_tasks: BackgroundTasks
):
    """Start the Intelligent Autopilot engine.
    
    .. deprecated:: Use /start-unified instead with mode='intelligent'
    """
    try:
        autopilot = get_intelligent_autopilot(
            symbol=config.symbol,
            exchange_id=config.exchange_id,
            timeframe=config.timeframe,
            interval=config.interval,
            paper_trading=config.paper_trading
        )
        
        if not autopilot.is_running:
            background_tasks.add_task(autopilot.start)
        
        return {
            "status": "started",
            "symbol": config.symbol,
            "timeframe": config.timeframe
        }
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))


@router.post("/intelligent/stop")
async def stop_intelligent_autopilot(symbol: str, timeframe: str = "1h"):
    """Stop the Intelligent Autopilot engine."""
    try:
        autopilot = get_intelligent_autopilot(symbol=symbol, timeframe=timeframe)
        autopilot.stop()
        return {"status": "stopped", "symbol": symbol}
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))


@router.get("/intelligent/status/{symbol:path}")
async def get_intelligent_status(symbol: str, timeframe: str = "1h"):
    """Get Intelligent Autopilot status."""
    try:
        autopilot = get_intelligent_autopilot(symbol=symbol, timeframe=timeframe)
        return autopilot.get_status()
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))


@router.get("/intelligent/performance")
async def get_intelligent_performance(
    strategy_name: Optional[str] = None,
    days: int = 30
):
    """Get strategy performance metrics."""
    try:
        tracker = get_performance_tracker()
        if strategy_name:
            metrics = tracker.calculate_metrics(strategy_name, period_days=days)
            return {"strategy": strategy_name, "metrics": metrics}
        else:
            # Get all strategies
            history = tracker.get_performance_history(days=days)
            if history.empty:
                return {"strategies": []}
            
            strategies = history['strategy_name'].unique()
            results = {}
            for strat in strategies:
                results[strat] = tracker.calculate_metrics(strat, period_days=days)
            
            return {"strategies": results}
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))


@router.get("/intelligent/training-stats")
async def get_training_stats(days: int = 365):
    """Get statistics about available training data.
    
    Returns:
        Dictionary with total samples and per-strategy counts
    """
    try:
        tracker = get_performance_tracker()
        counts = await tracker.get_strategy_sample_counts(days=days)
        
        return {
            "total_samples": sum(counts.values()),
            "strategy_counts": counts
        }
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))


@router.post("/intelligent/retrain")
async def retrain_model(force: bool = False, bootstrap: bool = True):
    """Manually trigger model retraining (Background Task).
    
    Offloads training to Celery worker.
    """
    try:
        # Get all bootstrap config to pass to worker
        config = get_config()
        symbols = config.get("autopilot.intelligent.bootstrap.symbols", ["BTC/USD", "ETH/USD"])
        days = config.get("autopilot.intelligent.bootstrap.days", 90)
        timeframe = config.get("autopilot.intelligent.bootstrap.timeframe", "1h")
        min_samples = config.get("autopilot.intelligent.bootstrap.min_samples_per_strategy", 10)
        
        # Submit to Celery with all configured parameters
        task = train_model_task.delay(
            force_retrain=force, 
            bootstrap=bootstrap, 
            symbols=symbols,
            days=days,
            timeframe=timeframe,
            min_samples_per_strategy=min_samples
        )
        
        return {
            "status": "queued",
            "message": "Model retraining started in background",
            "task_id": task.id
        }
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))


@router.get("/intelligent/model-info")
async def get_model_info():
    """Get ML model information."""
    try:
        selector = get_strategy_selector()
        return selector.get_model_info()
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))


@router.post("/intelligent/reset")
async def reset_model():
    """Reset/delete all saved ML models and training data.
    
    This clears all persisted model files AND training data from database,
    allowing for a fresh start with new features.
    """
    try:
        from pathlib import Path
        from src.core.database import get_database, MarketConditionsSnapshot, StrategyPerformance
        from sqlalchemy import delete
        
        # Get model directory
        model_dir = Path.home() / ".local" / "share" / "crypto_trader" / "models"
        
        deleted_count = 0
        if model_dir.exists():
            # Delete all strategy selector model files
            for model_file in model_dir.glob("strategy_selector_*.joblib"):
                model_file.unlink()
                deleted_count += 1
        
        # Clear training data from database
        db = get_database()
        db_cleared = 0
        try:
            async with db.get_session() as session:
                # Delete all market conditions snapshots
                result1 = await session.execute(delete(MarketConditionsSnapshot))
                # Delete all strategy performance records
                result2 = await session.execute(delete(StrategyPerformance))
                await session.commit()
                db_cleared = result1.rowcount + result2.rowcount
        except Exception as e:
            # Database clearing is optional - continue even if it fails
            pass
        
        # Reset the in-memory model state
        selector = get_strategy_selector()
        from src.autopilot.models import StrategySelectorModel
        selector.model = StrategySelectorModel(model_type="classifier")
        
        return {
            "status": "success",
            "message": f"Deleted {deleted_count} model file(s) and {db_cleared} training records. Model reset to untrained state.",
            "deleted_count": deleted_count,
            "db_records_cleared": db_cleared
        }
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))


# =============================================================================
# Multi-Symbol Autopilot Endpoints
# =============================================================================

@router.post("/multi-symbol/start")
async def start_multi_symbol_autopilot(
    config: MultiSymbolAutopilotConfig,
    background_tasks: BackgroundTasks
):
    """Start autopilot for multiple symbols simultaneously.
    
    Args:
        config: Multi-symbol autopilot configuration
        background_tasks: FastAPI background tasks
    """
    try:
        results = []
        for symbol in config.symbols:
             # Always use intelligent mode
             autopilot = get_intelligent_autopilot(
                 symbol=symbol,
                 exchange_id=config.exchange_id,
                 timeframe=config.timeframe,
                 interval=config.interval,
                 paper_trading=config.paper_trading
             )
             
             autopilot.enable_auto_execution = config.auto_execute
             
             if not autopilot.is_running:
                 # Set running flag synchronously before scheduling background task
                 autopilot._running = True
                 background_tasks.add_task(autopilot.start)
                 results.append({"symbol": symbol, "status": "started"})
             else:
                 results.append({"symbol": symbol, "status": "already_running"})
        
        return {
            "status": "success",
            "mode": "intelligent",
            "symbols": results
        }
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))


@router.post("/multi-symbol/stop")
async def stop_multi_symbol_autopilot(
    symbols: List[str],
    mode: str = "intelligent",
    timeframe: str = "1h"
):
    """Stop autopilot for multiple symbols.
    
    Args:
        symbols: List of symbols to stop
        mode: Autopilot mode (pattern or intelligent)
        timeframe: Timeframe for intelligent mode
    """
    try:
        results = []
        for symbol in symbols:
            # Always use intelligent mode
            autopilot = get_intelligent_autopilot(symbol=symbol, timeframe=timeframe)
            autopilot.stop()
            results.append({"symbol": symbol, "status": "stopped"})
        
        return {
            "status": "success",
            "symbols": results
        }
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))


@router.get("/multi-symbol/status")
async def get_multi_symbol_status(
    symbols: str = "",  # Comma-separated list
    mode: str = "intelligent",
    timeframe: str = "1h"
):
    """Get status for multiple symbols.
    
    Args:
        symbols: Comma-separated list of symbols (empty = all running)
        mode: Autopilot mode
        timeframe: Timeframe for intelligent mode
    """
    from src.autopilot.intelligent_autopilot import _intelligent_autopilots
    
    try:
        results = []
        
        if symbols:
            symbol_list = [s.strip() for s in symbols.split(",")]
        else:
            # Get all running autopilots (intelligent only)
            symbol_list = [key.split(":")[0] for key in _intelligent_autopilots.keys()]
        
        for symbol in symbol_list:
            try:
                autopilot = get_intelligent_autopilot(symbol=symbol, timeframe=timeframe)
                status = autopilot.get_status()
                status["symbol"] = symbol
                status["mode"] = "intelligent"
                results.append(status)
            except Exception:
                results.append({
                    "symbol": symbol,
                    "mode": "intelligent",
                    "running": False,
                    "error": "Not found"
                })
        
        return {
            "mode": mode,
            "symbols": results,
            "total_running": sum(1 for r in results if r.get("running", False))
        }
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))


# =============================================================================
# Unified Autopilot Endpoints (New)
# =============================================================================

@router.get("/modes")
async def get_autopilot_modes():
    """Get information about available autopilot modes.
    
    Returns mode descriptions, capabilities, tradeoffs, and comparison data.
    """
    try:
        return get_autopilot_mode_info()
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))


@router.post("/start-unified")
async def start_unified_autopilot(
    config: UnifiedAutopilotConfig,
    background_tasks: BackgroundTasks
):
    """Start autopilot with unified interface (Intelligent Mode only)."""
    try:
        # Validate mode (for backward compatibility of API clients sending mode)
        if config.mode and config.mode != "intelligent":
             # We allow it but will treat it as intelligent if possible, or raise error if critical
             pass

        # Start ML-based autopilot
        autopilot = get_intelligent_autopilot(
            symbol=config.symbol,
            exchange_id=config.exchange_id,
            timeframe=config.timeframe,
            interval=config.interval,
            paper_trading=config.paper_trading
        )
        
        # Set auto-execution if enabled
        if config.auto_execute:
            autopilot.enable_auto_execution = True
        
        if not autopilot.is_running:
            # Schedule background task (state management handled by autopilot.start via Redis)
            background_tasks.add_task(autopilot.start)
        
        return {
            "status": "started",
            "mode": "intelligent",
            "symbol": config.symbol,
            "timeframe": config.timeframe,
            "auto_execute": config.auto_execute
        }
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))


@router.post("/stop-unified")
async def stop_unified_autopilot(symbol: str, mode: str, timeframe: str = "1h"):
    """Stop autopilot for a symbol."""
    try:
        autopilot = get_intelligent_autopilot(symbol=symbol, timeframe=timeframe)
        autopilot.stop()
        
        return {"status": "stopped", "symbol": symbol, "mode": "intelligent"}
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))


@router.get("/status-unified/{symbol:path}")
async def get_unified_status(symbol: str, mode: str, timeframe: str = "1h"):
    """Get autopilot status for a symbol."""
    try:
        autopilot = get_intelligent_autopilot(symbol=symbol, timeframe=timeframe)
        # Use distributed status check (Redis)
        status = await autopilot.get_distributed_status()
        status["mode"] = "intelligent"
        return status
    except Exception as e:
        logger.error(f"Error getting unified status: {e}")
        raise HTTPException(status_code=500, detail=str(e))


@router.get("/bootstrap-config", response_model=BootstrapConfig)
async def get_bootstrap_config():
    """Get bootstrap training data configuration."""
    from src.core.config import get_config
    config = get_config()
    
    return BootstrapConfig(
        days=config.get("autopilot.intelligent.bootstrap.days", 90),
        timeframe=config.get("autopilot.intelligent.bootstrap.timeframe", "1h"),
        min_samples_per_strategy=config.get("autopilot.intelligent.bootstrap.min_samples_per_strategy", 10),
        symbols=config.get("autopilot.intelligent.bootstrap.symbols", ["BTC/USD", "ETH/USD"]),
    )


@router.put("/bootstrap-config")
async def update_bootstrap_config(settings: BootstrapConfig):
    """Update bootstrap training data configuration."""
    from src.core.config import get_config
    config = get_config()
    
    try:
        config.set("autopilot.intelligent.bootstrap.days", settings.days)
        config.set("autopilot.intelligent.bootstrap.timeframe", settings.timeframe)
        config.set("autopilot.intelligent.bootstrap.min_samples_per_strategy", settings.min_samples_per_strategy)
        config.set("autopilot.intelligent.bootstrap.symbols", settings.symbols)
        
        # Also update the strategy selector instance if it exists
        selector = get_strategy_selector()
        selector.bootstrap_days = settings.days
        selector.bootstrap_timeframe = settings.timeframe
        selector.min_samples_per_strategy = settings.min_samples_per_strategy
        selector.bootstrap_symbols = settings.symbols
        
        return {"status": "success", "message": "Bootstrap configuration updated"}
    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))


@router.get("/tasks/{task_id}")
async def get_task_status(task_id: str):
    """Get status of a background task."""
    try:
        task_result = AsyncResult(task_id)
        
        try:
            # Accessing status or result might raise an exception if deserialization fails
            status = task_result.status
            result_data = task_result.result if task_result.ready() else None
            meta_data = task_result.info if status == 'PROGRESS' else None
            
            # serialized exception handling
            if isinstance(result_data, Exception):
                result_data = {
                    "error": str(result_data),
                    "type": type(result_data).__name__,
                    "detail": str(result_data)
                }
            elif status == "FAILURE" and (not result_data or result_data == {}):
                # If failure but empty result, try to get traceback or use a default message
                tb = getattr(task_result, 'traceback', None)
                if tb:
                     result_data = {"error": "Task failed", "detail": str(tb)}
                else:
                     result_data = {"error": "Task failed with no error info", "detail": "Check worker logs for details"}

            result = {
                "task_id": task_id,
                "status": status,
                "result": result_data
            }
            
            if meta_data:
                result["meta"] = meta_data
                
            return result
            
        except Exception as inner_e:
            # If Celery fails to get status/result (e.g. serialization error), return FAILURE
            # This prevents 500 errors in the API when the task itself failed badly
            return {
                "task_id": task_id,
                "status": "FAILURE",
                "result": {"error": str(inner_e), "detail": "Failed to retrieve task status"},
                "meta": {"error": "Task retrieval failed"}
            }

    except Exception as e:
        raise HTTPException(status_code=500, detail=str(e))

