"""Compounding simulator - project capital growth over time.

Adapted from kriptokamu/src/strategy/scalping.py ActionTimeline pattern.
"""
from __future__ import annotations
from app.engine.base import BaseAlgorithm
from app.engine.context import AlgorithmContext


class CompoundingAlgorithm(BaseAlgorithm):
    algorithm_id = 'strategy.compounding'
    version = '1.0.0'
    category = 'strategy'
    display_name = 'Compounding Simulator'
    dependencies = ['technical.atr']

    # Simulation scenarios with win rate and stop loss (realistic projections)
    # Philosophy: small certain profit repeated frequently
    SCENARIOS = [
        {'name': 'Conservative', 'profit_pct': 1.2, 'trades_day': 1, 'win_rate': 0.80, 'sl_pct': 0.8},
        {'name': 'Moderate', 'profit_pct': 1.8, 'trades_day': 2, 'win_rate': 0.75, 'sl_pct': 1.0},
        {'name': 'Aggressive', 'profit_pct': 2.5, 'trades_day': 3, 'win_rate': 0.65, 'sl_pct': 1.5},
    ]

    # Stock-adjusted scenarios (fewer trades per day due to market hours)
    STOCK_SCENARIOS = [
        {'name': 'Conservative', 'profit_pct': 1.2, 'trades_day': 1, 'win_rate': 0.80, 'sl_pct': 0.8},
        {'name': 'Moderate', 'profit_pct': 1.8, 'trades_day': 1, 'win_rate': 0.75, 'sl_pct': 1.0},
        {'name': 'Aggressive', 'profit_pct': 2.5, 'trades_day': 2, 'win_rate': 0.65, 'sl_pct': 1.5},
    ]

    def compute(self, ctx: AlgorithmContext) -> AlgorithmContext:
        fee_roundtrip = ctx.buy_fee_pct + ctx.sell_fee_pct + ctx.sell_tax_pct
        active_capital = ctx.capital_idr * (ctx.active_pct / 100)

        # Use stock-adjusted scenarios for stocks (fewer trades due to limited hours)
        scenarios = self.STOCK_SCENARIOS if ctx.asset_type in ('stock', 'stock_us') else self.SCENARIOS

        simulations = []
        for scenario in scenarios:
            win_rate = scenario.get('win_rate', 0.75)
            sl_pct = scenario.get('sl_pct', 1.5)
            # Expected value per trade accounting for losses
            # Win: +profit - fees, Lose: -stop_loss - fees
            net_profit_per_trade = (
                win_rate * (scenario['profit_pct'] - fee_roundtrip)
                - (1 - win_rate) * (sl_pct + fee_roundtrip)
            )
            if net_profit_per_trade <= 0:
                continue

            daily_trades = scenario['trades_day']
            projections = []
            capital = active_capital

            for day in [1, 7, 14, 30]:
                # For stocks: only count business days (5 of 7 calendar days)
                if ctx.asset_type in ('stock', 'stock_us'):
                    trading_days = int(day * 5 / 7)
                    trading_days = max(trading_days, 1)
                else:
                    trading_days = day
                total_trades = daily_trades * trading_days
                for _ in range(total_trades):
                    capital *= (1 + net_profit_per_trade / 100)
                profit = capital - active_capital
                projections.append({
                    'days': day,
                    'capital': round(capital, 0),
                    'profit': round(profit, 0),
                    'profit_pct': round((profit / active_capital) * 100, 2),
                    'total_trades': total_trades,
                })
                capital = active_capital  # Reset for each independent projection

            # Proper compounding calculation (30-day continuous)
            capital_30d = active_capital
            trading_days_30d = int(30 * 5 / 7) if ctx.asset_type in ('stock', 'stock_us') else 30
            total_trades_30d = daily_trades * trading_days_30d
            for _ in range(total_trades_30d):
                capital_30d *= (1 + net_profit_per_trade / 100)

            simulations.append({
                'scenario': scenario['name'],
                'profit_per_trade': scenario['profit_pct'],
                'win_rate': win_rate,
                'sl_pct': sl_pct,
                'net_per_trade': round(net_profit_per_trade, 2),
                'trades_per_day': daily_trades,
                'projections': projections,
                'compound_30d': {
                    'capital': round(capital_30d, 0),
                    'profit': round(capital_30d - active_capital, 0),
                    'profit_pct': round((capital_30d - active_capital) / active_capital * 100, 2),
                },
            })

        ctx.strategy['compounding'] = {
            'initial_capital': round(active_capital, 0),
            'fee_roundtrip': fee_roundtrip,
            'simulations': simulations,
        }
        return ctx
