using Managing.Core;
using Managing.Domain.Candles;
using Managing.Domain.Indicators;
using Managing.Domain.Shared.Rules;
using Managing.Domain.Strategies.Base;
using Skender.Stock.Indicators;
using static Managing.Common.Enums;

namespace Managing.Domain.Strategies.Signals;

public class SuperTrendIndicatorBase : IndicatorBase
{
    public List<LightSignal> Signals { get; set; }

    public SuperTrendIndicatorBase(string name, int period, double multiplier) : base(name, IndicatorType.SuperTrend)
    {
        Signals = new List<LightSignal>();
        Period = period;
        Multiplier = multiplier;
        MinimumHistory = 100 + Period.Value;
    }

    public override List<LightSignal> Run(HashSet<Candle> candles)
    {
        if (candles.Count <= MinimumHistory)
        {
            return null;
        }

        try
        {
            var superTrend = candles.GetSuperTrend(Period.Value, Multiplier.Value).Where(s => s.SuperTrend.HasValue);
            var superTrendCandle = MapSuperTrendToCandle(superTrend, candles.TakeLast(MinimumHistory));

            if (superTrendCandle.Count == 0)
                return null;

            var previousCandle = superTrendCandle[0];
            foreach (var currentCandle in superTrendCandle.Skip(1))
            {
                // // Short
                // if (currentCandle.Close < previousCandle.SuperTrend && previousCandle.Close > previousCandle.SuperTrend)
                // {
                //     AddSignal(currentCandle, TradeDirection.Short, Confidence.Medium);
                // }
                //
                // // Long
                // if (currentCandle.Close > previousCandle.SuperTrend && previousCandle.Close < previousCandle.SuperTrend)
                // {
                //     AddSignal(currentCandle, TradeDirection.Long, Confidence.Medium);
                // }

                if (currentCandle.SuperTrend < currentCandle.Close)
                {
                    AddSignal(currentCandle, TradeDirection.Long, Confidence.Medium);
                }
                else if (currentCandle.SuperTrend > currentCandle.Close)
                {
                    AddSignal(currentCandle, TradeDirection.Short, Confidence.Medium);
                }

                previousCandle = currentCandle;
            }

            return Signals.Where(s => s.Confidence != Confidence.None).OrderBy(s => s.Date).ToList();
        }
        catch (RuleException)
        {
            return null;
        }
    }

    public override IndicatorsResultBase GetIndicatorValues(HashSet<Candle> candles)
    {
        return new IndicatorsResultBase()
        {
            SuperTrend = candles.GetSuperTrend(Period.Value, Multiplier.Value).Where(s => s.SuperTrend.HasValue)
                .ToList()
        };
    }

    private List<CandleSuperTrend> MapSuperTrendToCandle(IEnumerable<SuperTrendResult> superTrend,
        IEnumerable<Candle> candles)
    {
        var superTrends = new List<CandleSuperTrend>();
        foreach (var candle in candles)
        {
            var currentSuperTrend = superTrend.Find(candle.Date);
            if (currentSuperTrend != null)
            {
                superTrends.Add(new CandleSuperTrend()
                {
                    Close = candle.Close,
                    Open = candle.Open,
                    Date = candle.Date,
                    Ticker = candle.Ticker,
                    Exchange = candle.Exchange,
                    SuperTrend = currentSuperTrend.SuperTrend.Value,
                    LowerBand = currentSuperTrend.LowerBand,
                    UpperBand = currentSuperTrend.UpperBand,
                });
            }
        }

        return superTrends;
    }

    private void AddSignal(CandleSuperTrend candleSignal, TradeDirection direction, Confidence confidence)
    {
        var signal = new LightSignal(MiscExtensions.ParseEnum<Ticker>(candleSignal.Ticker), direction, confidence,
            candleSignal, candleSignal.Date,
            candleSignal.Exchange, Type, SignalType, Name);
        if (!Signals.Any(s => s.Identifier == signal.Identifier))
        {
            Signals.AddItem(signal);
        }
    }


    private class CandleSuperTrend : Candle
    {
        public decimal SuperTrend { get; internal set; }
        public decimal? LowerBand { get; internal set; }
        public decimal? UpperBand { get; internal set; }
    }
}