import logger from '../utils/logger.js';

export enum SignalType {
    BUY = 'BUY',
    SELL = 'SELL',
    NONE = 'NONE'
}

export interface StrategyResult {
    signal: SignalType;
    ema: number;
    rsi: number;
    changed: boolean;
}

export class DirectionTracker {
    private lastSignal: SignalType = SignalType.NONE;

    /**
     * Advanced Strategy: EMA + RSI
     * BUY: Price > EMA-20 AND RSI < 70 (not overbought)
     * SELL: Price < EMA-20 AND RSI > 30 (not oversold)
     * 
     * Includes a state machine to prevent duplicate signals.
     */
    public calculateDirection(candles: any[]): StrategyResult {
        // Need enough data for RSI (14) and EMA (20)
        if (candles.length < 20) {
            return { signal: SignalType.NONE, ema: 0, rsi: 0, changed: false };
        }

        const latestCandle = candles[candles.length - 1];
        const latestClose = latestCandle.close;

        // 1. Calculate EMA-20
        const ema20 = this.calculateEMA(candles.map(c => c.close), 20);

        // 2. Calculate RSI-14
        const rsi14 = this.calculateRSI(candles.map(c => c.close), 14);

        // 3. Signal Logic
        let currentSignal = SignalType.NONE;

        if (latestClose > ema20 && rsi14 < 70) {
            currentSignal = SignalType.BUY;
        } else if (latestClose < ema20 && rsi14 > 30) {
            currentSignal = SignalType.SELL;
        }

        // 4. State Machine (Check if signal changed to avoid duplicates)
        const changed = currentSignal !== SignalType.NONE && currentSignal !== this.lastSignal;

        if (changed) {
            logger.info(`🚨 New Strategy Signal: ${currentSignal} (EMA: ${ema20.toFixed(2)}, RSI: ${rsi14.toFixed(2)})`);
            this.lastSignal = currentSignal;
        }

        return {
            signal: currentSignal,
            ema: ema20,
            rsi: rsi14,
            changed
        };
    }

    private calculateEMA(data: number[], period: number): number {
        if (data.length === 0) return 0;
        const k = 2 / (period + 1);
        let ema = data[0] || 0;
        for (let i = 1; i < data.length; i++) {
            const current = data[i] || 0;
            ema = current * k + ema * (1 - k);
        }
        return ema;
    }

    private calculateRSI(data: number[], period: number): number {
        if (data.length <= period) return 50; // Default if not enough data

        let gains = 0;
        let losses = 0;

        // First average
        for (let i = 1; i <= period; i++) {
            const diff = data[i] - data[i - 1];
            if (diff >= 0) gains += diff;
            else losses -= diff;
        }

        let avgGain = gains / period;
        let avgLoss = losses / period;

        // Smoothing
        for (let i = period + 1; i < data.length; i++) {
            const diff = data[i] - data[i - 1];
            if (diff >= 0) {
                avgGain = (avgGain * (period - 1) + diff) / period;
                avgLoss = (avgLoss * (period - 1)) / period;
            } else {
                avgGain = (avgGain * (period - 1)) / period;
                avgLoss = (avgLoss * (period - 1) - diff) / period;
            }
        }

        if (avgLoss === 0) return 100;
        const rs = avgGain / avgLoss;
        return 100 - (100 / (1 + rs));
    }
}
