"""
=========================================
CV6 AI Trading OS
Indicator Manager
=========================================
"""

from app.indicators.indicator_validator import IndicatorValidator


class IndicatorManager:

    @staticmethod
    def calculate_ema_series(prices: list[float], period: int):
        validation = IndicatorValidator.validate_prices(prices, period)

        if not validation["valid"]:
            return validation

        ema_values = []

        sma = sum(prices[:period]) / period
        multiplier = 2 / (period + 1)

        ema = sma
        ema_values.append(round(ema, 2))

        for price in prices[period:]:
            ema = (price * multiplier) + (ema * (1 - multiplier))
            ema_values.append(round(ema, 2))

        return ema_values

    @staticmethod
    def calculate_ema(prices: list[float], period: int):

        ema_series = IndicatorManager.calculate_ema_series(
            prices,
            period
        )

        if isinstance(ema_series, dict):
            return ema_series

        return ema_series[-1]

    @staticmethod
    def calculate_rsi(prices: list[float], period: int = 14):

        validation = IndicatorValidator.validate_prices(prices, period)

        if not validation["valid"]:
            return validation

        gains = []
        losses = []

        for i in range(1, len(prices)):
            change = prices[i] - prices[i - 1]

            if change > 0:
                gains.append(change)
                losses.append(0)
            else:
                gains.append(0)
                losses.append(abs(change))

        avg_gain = sum(gains[:period]) / period
        avg_loss = sum(losses[:period]) / period

        if avg_loss == 0:
            return 100.0

        rs = avg_gain / avg_loss
        rsi = 100 - (100 / (1 + rs))

        return round(rsi, 2)

    @staticmethod
    def calculate_macd(
        prices: list[float],
        fast_period: int = 12,
        slow_period: int = 26
    ):
        """
        Calculate MACD
        """

        validation = IndicatorValidator.validate_prices(
            prices,
            slow_period
        )

        if not validation["valid"]:
            return validation

        fast = IndicatorManager.calculate_ema(
            prices,
            fast_period
        )

        slow = IndicatorManager.calculate_ema(
            prices,
            slow_period
        )

        if isinstance(fast, dict):
            return fast

        if isinstance(slow, dict):
            return slow

        macd = fast - slow

        return round(macd, 2)
    @staticmethod
    def calculate_sma(
        prices: list[float],
        period: int = 20
    ):

        from app.indicators.sma import SMAIndicator

        result = SMAIndicator.calculate(
            prices,
            period
        )

        if isinstance(result, dict):
            return result

        return result[-1]

    @staticmethod
    def calculate_atr(
        data,
        period: int = 14
    ):

        from app.indicators.atr import ATRIndicator

        return ATRIndicator.latest(
            data,
            period
        )

    @staticmethod
    def calculate_bollinger(
        prices,
        period: int = 20,
        std_dev: int = 2
    ):

        from app.indicators.bollinger_bands import (
            BollingerBandsIndicator
        )

        return BollingerBandsIndicator.latest(
            prices,
            period,
            std_dev
        )

    @staticmethod
    def calculate_supertrend(
        data,
        period: int = 10,
        multiplier: float = 3.0
    ):

        from app.indicators.supertrend import (
            SuperTrendIndicator
        )

        return SuperTrendIndicator.latest(
            data,
            period,
            multiplier
        )

    @staticmethod
    def calculate_vwap(
        data
    ):

        from app.indicators.vwap import VWAPIndicator

        return VWAPIndicator.latest(
            data
        )