using cAlgo.API;
using cAlgo.API.Indicators;
using System;

namespace cAlgo.Robots
{
    // A simple trading strategy based on HMA slope and candle patterns.
    [Robot(AccessRights = AccessRights.None)]
    public class HmaBiasStrategy : Robot
    {
        [Parameter("HMA Period", DefaultValue = 20, Group = "Parameters")]
        public int HmaPeriod { get; set; }

        [Parameter("ATR Period", DefaultValue = 14, Group = "Parameters")]
        public int AtrPeriod { get; set; }

        [Parameter("ATR Multiplier for SL", DefaultValue = 4.0, Group = "Parameters")]
        public double AtrMultiplier { get; set; }

        [Parameter("Volume (Units)", DefaultValue = 10000, MinValue = 1000, Group = "Parameters")]
        public double VolumeInUnits { get; set; }
        
        [Parameter("Wick Ratio (Lower > Upper * Ratio)", DefaultValue = 2.0, Group = "Parameters")]
        public double WickRatio { get; set; }

        [Parameter("Trade Label", DefaultValue = "HmaBiasStrategy", Group = "Parameters")]
        public string Label { get; set; }

        // Hull Moving Average for trend direction and momentum.
        private HullMovingAverage _hma;
        // Average True Range for Stop Loss calculation.
        private AverageTrueRange _atr;
        
        // Holds the currently open position.
        private Position _position;
        // Tracks the bar index when a position was opened.
        private int _entryBarIndex;

        // Initialize indicators and state variables.
        protected override void OnStart()
        {
            _hma = Indicators.HullMovingAverage(Bars.ClosePrices, HmaPeriod);
            _atr = Indicators.AverageTrueRange(AtrPeriod, MovingAverageType.Simple);
            _position = null;
            _entryBarIndex = -1;
        }

        // Main logic, executed on every bar close.
        protected override void OnBar()
        {
            // First, check if we need to close the existing position.
            if ((_position != null) && (Bars.Count - 1 > _entryBarIndex))
            {
                ClosePosition(_position);
                _position = null;
            }

            // If no position is open, check for a new entry signal.
            if (_position == null)
            {
                // Ensure we have enough data for the lookback.
                if (Bars.Count < HmaPeriod + 5)
                {
                    return;
                }

                // --- Bias Calculation on PREVIOUS bar ---
                var hmaPrev = _hma.Result.Last(2);
                var hmaPrev2 = _hma.Result.Last(3);
                var hmaPrev3 = _hma.Result.Last(4);

                var slopeOnPrevBar = hmaPrev - hmaPrev2;
                var slopeOnPrevBar2 = hmaPrev2 - hmaPrev3;
                
                // Check if the bias was bullish on the bar that just closed before this one.
                bool previousBarHadBullishBias = (slopeOnPrevBar > 0) && (slopeOnPrevBar > slopeOnPrevBar2);
                
                if (previousBarHadBullishBias)
                {
                    // --- Signal Check on CURRENT bar ---
                    var currentBar = Bars.LastBar;
                    var previousBar = Bars.Last(1); // This is the bar that had the bias
                    bool signalTriggered = false;

                    // Signal 1: Current bar's close is above the previous bar's high.
                    if (currentBar.Close > previousBar.High)
                    {
                        signalTriggered = true;
                    }

                    // Signal 2: Current bar is a bullish candle with a long lower wick.
                    bool isBullishCandle = currentBar.Close > currentBar.Open;
                    if ((!signalTriggered) && (isBullishCandle))
                    {
                        double lowerWick = currentBar.Open - currentBar.Low;
                        double upperWick = currentBar.High - currentBar.Close;
                        if (lowerWick > (upperWick * WickRatio))
                        {
                            signalTriggered = true;
                        }
                    }
                    
                    // --- Execute Trade ---
                    if (signalTriggered)
                    {
                        var volumeInUnits = Symbol.NormalizeVolumeInUnits(VolumeInUnits, RoundingMode.ToNearest);
                        var stopLossPips = _atr.Result.LastValue * AtrMultiplier / Symbol.PipSize;
                        var result = ExecuteMarketOrder(TradeType.Buy, Symbol.Name, volumeInUnits, Label, stopLossPips, null);

                        if (result.IsSuccessful)
                        {
                            _position = result.Position;
                            _entryBarIndex = Bars.Count - 1;
                        }
                    }
                }
            }
        }

        // Ensure any open position is closed when the cBot stops.
        protected override void OnStop()
        {
            if (_position != null)
            {
                ClosePosition(_position);
                _position = null;
            }
        }
    }
}