import asyncio
from typing import List, Dict, Union
from uuid import uuid4

from app.models import Strategy, StrategyType, Position, AssetClass, Scenario, SimulationRun, SimulationStatus
from app.engine import engine
from app.reporting import RiskReport
from app.analysis_models import RobustnessMatrix, ScenarioResult

def create_strategy(name: str, allocations: List[Dict[str, Union[str, float]]]) -> Strategy:
    """
    Helper to create a Strategy object from simple dict list.
    allocations = [{"ticker": "SPY", "weight": 0.6}, ...]
    """
    positions = []
    for alloc in allocations:
        pos = Position(
            ticker=alloc["ticker"],
            weight=alloc["weight"],
            asset_class=AssetClass.EQUITY # Default for now
        )
        positions.append(pos)
        
    return Strategy(
        id=uuid4(),
        name=name,
        strategy_type=StrategyType.STATIC_WEIGHTS,
        allocation=positions
    )

def analyze(strategy: Strategy) -> RiskReport:
    """
    Runs the full robustness analysis suite on the given strategy.
    Returns a RiskReport object.
    """
    # Define Scenarios (Mirroring the API logic)
    scenarios = [
        Scenario(name="Historical Baseline", scenario_type="historical_replay"),
        Scenario(name="2008 Crash Replay", scenario_type="regime_stress", parameters={"shock": "crash"}),
        Scenario(name="Volatility Spike (2x)", scenario_type="regime_stress", parameters={"shock": "volatility", "vol_mult": 2.0}),
        Scenario(name="Correlation Breakdown", scenario_type="regime_stress", parameters={"shock": "correlation", "corr_factor": 0.9})
    ]
    
    results = []
    total_score = 0.0
    
    for scen in scenarios:
        run = SimulationRun(strategy_id=strategy.id, scenario_id=scen.id)
        
        # Execute engine method synchronously
        executed_run = engine.run_simulation(run, strategy, scen)
        
        # Collect results
        res = ScenarioResult(
            scenario_name=scen.name,
            robustness_score=executed_run.robustness_score or 0.0,
            max_drawdown=executed_run.max_drawdown or 0.0,
            sharpe_ratio=executed_run.sharpe_ratio or 0.0
        )
        results.append(res)
        total_score += res.robustness_score
            
    avg_score = total_score / len(results) if results else 0.0
    
    matrix = RobustnessMatrix(
        strategy_id=strategy.id,
        aggregate_score=avg_score,
        scenario_results=results
    )
    
    return RiskReport(matrix)
