import { config } from '../../config/index.js';
import { IRule, MarketContext, RuleResult, SignalDirection } from './types.js';

export class RiskManagementRule implements IRule {
    public name = 'RiskManagementRule';

    public isEnabled(): boolean {
        return config.PRO_STRATEGY.ENABLED_RULES.includes('risk_management');
    }

    public async check(context: MarketContext, params?: Record<string, any>): Promise<RuleResult> {
        const atrPeriod = Number(params?.atrPeriod ?? config.PRO_STRATEGY.PARAMETERS.ATR_PERIOD);
        const slMultiplier = Number(params?.slMultiplier ?? config.PRO_STRATEGY.PARAMETERS.SL_MULTIPLIER);
        let maxRiskPercent = Number(params?.maxRisk ?? 5);
        if (Number.isFinite(maxRiskPercent) && maxRiskPercent > 0 && maxRiskPercent <= 1) {
            maxRiskPercent = maxRiskPercent * 100;
        }

        // Need candles to calculate ATR
        // Let's assume we use 1H candles for ATR calculation (faster reaction than 4H)
        if (context.candles1h.length < 20) {
            return {
                ruleName: this.name,
                passed: false,
                reason: 'Insufficient 1H data for ATR Risk Calc'
            };
        }

        const atr = this.calculateATR(context.candles1h, atrPeriod);
        const currentPrice = context.currentPrice;

        // Calculate Stop Loss Distance
        // Standard: 1.5 * ATR
        const slDistance = atr * slMultiplier;
        const riskPercent = currentPrice > 0 ? (slDistance / currentPrice) * 100 : 0;

        // Calculate Position Risk
        // If we have a $1000 account and risk 1% = $10 risk.
        // Size = RiskAmount / SL_Distance
        // Since we don't have account balance connected here easily, we will return the "Unit Size" multiplier.
        // Or simply return the calculated SL prices.

        const longSL = currentPrice - slDistance;
        const shortSL = currentPrice + slDistance;
        const isWithinRiskLimit = !Number.isFinite(maxRiskPercent) || maxRiskPercent <= 0 || riskPercent <= maxRiskPercent;

        return {
            ruleName: this.name,
            passed: isWithinRiskLimit,
            signal: SignalDirection.NONE,
            reason: isWithinRiskLimit
                ? `Risk Calculated (ATR: ${atr.toFixed(2)}, stop distance ${riskPercent.toFixed(2)}%)`
                : `Risk too high (${riskPercent.toFixed(2)}% > max ${maxRiskPercent.toFixed(2)}%)`,
            metadata: {
                atr,
                atrPeriod,
                slDistance,
                slMultiplier,
                riskPercent,
                maxRiskPercent,
                suggestedStopLoss: {
                    buy: longSL,
                    sell: shortSL
                }
            }
        };
    }

    private calculateATR(candles: any[], period: number): number {
        // Simple TR calculation
        let trSum = 0;

        // Need at least period + 1 candles to start
        if (candles.length <= period) return 0;

        // Calculate TR for the last 'period' candles
        // Note: standard ATR is smoothed, this is a simple average for robustness in this snippet
        // Better: standard Wilder's smoothing

        // Simplified Average TR for stability
        const recentCandles = candles.slice(-period);
        let sumTR = 0;

        for (let i = 1; i < recentCandles.length; i++) {
            const high = recentCandles[i].high;
            const low = recentCandles[i].low;
            const prevClose = recentCandles[i - 1].close;

            const tr = Math.max(
                high - low,
                Math.abs(high - prevClose),
                Math.abs(low - prevClose)
            );
            sumTR += tr;
        }

        return sumTR / (period - 1);
    }
}
