# src/portfolio/portfolio_engine.py

from typing import Dict
import pandas as pd

from src.core.engine import Engine
from src.portfolio.allocation import Allocation
from src.portfolio.portfolio_result import PortfolioResult


class PortfolioEngine:
    """
    Ejecuta múltiples engines en paralelo y combina resultados
    alineando las curvas por timestamp.
    """

    def __init__(
        self,
        engines: Dict[str, Engine],
        allocation: Allocation,
        initial_capital: float,
    ):
        allocation.validate()
        self.engines = engines
        self.allocation = allocation
        self.initial_capital = initial_capital

    def run(self, data):
        results = {}
        equity_series = []

        for name, engine in self.engines.items():
            res = engine.run(data)
            results[name] = res

            weight = self.allocation.weights[name]

            # --- construir serie con timestamps ---
            eq = pd.Series(
                res["equity_curve"],
                index=pd.to_datetime(res["timestamps"]),
                name=name,
            )

            # --- aplicar peso ---
            eq_weighted = eq * weight
            equity_series.append(eq_weighted)

        # --------------------------------------------------
        # Alinear todas las curvas por timestamp
        # --------------------------------------------------
        df = pd.concat(equity_series, axis=1)

        # Forward fill para periodos sin trades
        df = df.ffill()

        # Si alguna empieza más tarde, asumimos capital inicial ponderado
        df = df.fillna(self.initial_capital * 0.0)

        # Equity total del portfolio
        portfolio_equity = df.sum(axis=1)

        return PortfolioResult(
            equity_curve=portfolio_equity.tolist(),
            final_capital=float(portfolio_equity.iloc[-1]),
            components=results,
        )
