using System;
using cAlgo.API;
using cAlgo.API.Indicators;
// using cAlgo.API.Extensions; // Removed faulty namespace reference

namespace cAlgo.Indicators
{
    // Aggregates signals from HmaSmaCrossoverSignal on two timeframes
    [Indicator(IsOverlay = false, TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class MultiTimeframeSignalAggregator : Indicator
    {
        [Parameter("HTF TimeFrame (B)", DefaultValue = "m2")]
        public TimeFrame HtfTimeFrame { get; set; }

        [Parameter("HMA A Period (Fast)", DefaultValue = 20, Group = "Indicator Settings")]
        public int HmaAPeriod { get; set; }

        [Parameter("HMA B Period (Slow)", DefaultValue = 250, Group = "Indicator Settings")]
        public int HmaBPeriod { get; set; }

        [Parameter("SMA C Period (Base)", DefaultValue = 200, Group = "Indicator Settings")]
        public int SmaCPeriod { get; set; }

        // Output for final Buy signals
        [Output("Buy Signal", LineColor = "Yellow", PlotType = PlotType.Points, Thickness = 8)]
        public IndicatorDataSeries BuySignal { get; set; }

        // Output for final Sell signals
        [Output("Sell Signal", LineColor = "Red", PlotType = PlotType.Points, Thickness = 8)]
        public IndicatorDataSeries SellSignal { get; set; }

        // Indicator A (Current Chart)
        private HmaSmaCrossoverSignal _indicatorA;
        
        // Indicator B (Higher Timeframe)
        private HmaSmaCrossoverSignal _indicatorB;
        private Bars _htfBars;

        // State variables to track the last signal on the HTF
        private DateTime _lastHtfBuyTime = DateTime.MinValue;
        private DateTime _lastHtfSellTime = DateTime.MinValue;
        private int _lastHtfIndexChecked = -1;

        protected override void Initialize()
        {
            // Get the Bars for the higher timeframe
            _htfBars = MarketData.GetBars(HtfTimeFrame);

            // Initialize Indicator A (current timeframe)
            _indicatorA = Indicators.GetIndicator<HmaSmaCrossoverSignal>(HmaAPeriod, HmaBPeriod, SmaCPeriod);
            
            // Initialize Indicator B (higher timeframe)
            _indicatorB = Indicators.GetIndicator<HmaSmaCrossoverSignal>(_htfBars, HmaAPeriod, HmaBPeriod, SmaCPeriod);
        }

        public override void Calculate(int index)
        {
            // Reset signals for the current bar (index) and the previous bar (index - 1)
            // This handles the repainting nature of the underlying signal
            BuySignal[index] = double.NaN;
            SellSignal[index] = double.NaN;
            if (index > 0)
            {
                BuySignal[index - 1] = double.NaN;
                SellSignal[index - 1] = double.NaN;
            }

            // Need at least 2 bars for index-1 signals
            if (index < 2)
            {
                return;
            }

            // --- 1. Update HTF (Indicator B) State ---
            
            // Manual replacement for GetIndexByTime
            int htfIndex = GetHtfIndex(Bars.OpenTimes[index]);
            if (htfIndex == -1)
            {
                // Not enough HTF data
                return;
            }

            // Scan HTF bars from where we left off up to the current htfIndex
            // We scan efficiently, only checking new bars
            int scanFromIndex = Math.Max(0, _lastHtfIndexChecked + 1);
            int scanToIndex = htfIndex;

            for (int i = scanFromIndex; i <= scanToIndex; i++)
            {
                // The signal indicator needs at least 2 bars (i and i-1) to check for signals
                if (i < 2) continue;

                // Check for confirmed signals at (i-1)
                if (!double.IsNaN(_indicatorB.BuySignal[i - 1]))
                {
                    _lastHtfBuyTime = _htfBars.OpenTimes[i - 1];
                }
                if (!double.IsNaN(_indicatorB.SellSignal[i - 1]))
                {
                    _lastHtfSellTime = _htfBars.OpenTimes[i - 1];
                }
            }
            // Remember how far we've scanned
            _lastHtfIndexChecked = scanToIndex;
            
            // --- 2. Check Current TF (Indicator A) Signal ---
            
            // Get the confirmed signal from the *previous* bar (index - 1)
            double currentBuySignal = _indicatorA.BuySignal[index - 1];
            double currentSellSignal = _indicatorA.SellSignal[index - 1];
            
            bool hasCurrentBuy = !double.IsNaN(currentBuySignal);
            bool hasCurrentSell = !double.IsNaN(currentSellSignal);

            if (!hasCurrentBuy && !hasCurrentSell)
            {
                // No signal on current TF
                return;
            }

            // --- 3. Apply Aggregation Logic ---
            
            // Buy signal: Current TF shows Buy AND the last HTF signal was also a Buy
            if (hasCurrentBuy && (_lastHtfBuyTime > _lastHtfSellTime))
            {
                // Place the signal at index - 1, using the value from Indicator A
                BuySignal[index - 1] = currentBuySignal;
            }

            // Sell signal: Current TF shows Sell AND the last HTF signal was also a Sell
            if (hasCurrentSell && (_lastHtfSellTime > _lastHtfBuyTime))
            {
                // Place the signal at index - 1, using the value from Indicator A
                SellSignal[index - 1] = currentSellSignal;
            }
        }
        
        // Manual implementation of GetIndexByTime
        // Finds the index of the bar that was open at the specified time
        private int GetHtfIndex(DateTime time)
        {
            // Loop backwards for efficiency, assuming time is recent
            for (int i = _htfBars.Count - 1; i >= 0; i--)
            {
                // If the bar's open time is at or before the requested time, this is the bar
                if (_htfBars.OpenTimes[i] <= time)
                {
                    return i;
                }
            }
            // Time is before the first bar
            return -1;
        }
    }
}