using System;
using System.Net.Http;
using System.Threading.Tasks;
using cAlgo.API;
using cAlgo.API.Indicators;
using cAlgo.API.Internals;

namespace cAlgo.Robots
{
    public enum TradingDirection
    {
        Both,
        LongOnly,
        ShortOnly
    }

    [Robot(TimeZone = TimeZones.UTC, AccessRights = AccessRights.FullAccess)]
    public class SmaHmaNotification : Robot
    {
        #region Parameters

        [Parameter("SMA Period", DefaultValue = 200, MinValue = 1)]
        public int SmaPeriod { get; set; }

        [Parameter("HMA Period", DefaultValue = 250, MinValue = 1)]
        public int HmaPeriod { get; set; }

        [Parameter("Trading Direction", DefaultValue = TradingDirection.Both)]
        public TradingDirection AllowedDirection { get; set; }

        [Parameter("Sound File Path", DefaultValue = @"C:\Windows\Media\Alarm05.wav")]
        public string SoundFilePath { get; set; }

        [Parameter("Telegram Bot Token", DefaultValue = "8569913524:AAE9RGsvkBPa0yhTFCKBjVeST0fuzdOx5w0")]
        public string TelegramBotToken { get; set; }

        [Parameter("Telegram Chat ID", DefaultValue = "5171721381")]
        public string TelegramChatId { get; set; }

        #endregion

        #region Fields

        private SimpleMovingAverage _sma;
        private HullMovingAverage _hma;
        private HttpClient _httpClient;

        private bool _waitingForSmaRise;
        private bool _waitingForSmaFall;

        #endregion

        protected override void OnStart()
        {
            _sma = Indicators.SimpleMovingAverage(Bars.ClosePrices, SmaPeriod);
            _hma = Indicators.HullMovingAverage(Bars.ClosePrices, HmaPeriod);

            _httpClient = new HttpClient();

            // TriggerSignal("START", $"Bot started. Direction: {AllowedDirection}");
        }

        protected override void OnStop()
        {
            _httpClient?.Dispose();
        }

        protected override void OnBarClosed()
        {
            if (Bars.Count <= Math.Max(SmaPeriod, HmaPeriod) + 1)
            {
                return;
            }

            double smaClosed = _sma.Result.Last(0);
            double smaPrev   = _sma.Result.Last(1);
            
            double hmaClosed = _hma.Result.Last(0);
            double hmaPrev   = _hma.Result.Last(1);

            bool isSmaRising = smaClosed > smaPrev;
            bool isSmaFalling = smaClosed < smaPrev;

            bool isCrossUp = (hmaPrev <= smaPrev) && (hmaClosed > smaClosed);
            bool isCrossDown = (hmaPrev >= smaPrev) && (hmaClosed < smaClosed);

            bool isHmaAbove = hmaClosed > smaClosed;
            bool isHmaBelow = hmaClosed < smaClosed;

            if (AllowedDirection == TradingDirection.Both || AllowedDirection == TradingDirection.LongOnly)
            {
                if (isCrossUp)
                {
                    _waitingForSmaFall = false; 

                    if (isSmaRising)
                    {
                        TriggerSignal("BUY", "SMA Rising + HMA CrossUp (Immediate)");
                        _waitingForSmaRise = false;
                    }
                    else
                    {
                        _waitingForSmaRise = true;
                    }
                }
                else if (_waitingForSmaRise)
                {
                    if (!isHmaAbove)
                    {
                        _waitingForSmaRise = false;
                    }
                    else if (isSmaRising)
                    {
                        TriggerSignal("BUY", "SMA Started Rising after HMA CrossUp (Delayed)");
                        _waitingForSmaRise = false;
                    }
                }
            }
            else
            {
                _waitingForSmaRise = false;
            }

            if (AllowedDirection == TradingDirection.Both || AllowedDirection == TradingDirection.ShortOnly)
            {
                if (isCrossDown)
                {
                    _waitingForSmaRise = false;

                    if (isSmaFalling)
                    {
                        TriggerSignal("SELL", "SMA Falling + HMA CrossDown (Immediate)");
                        _waitingForSmaFall = false;
                    }
                    else
                    {
                        _waitingForSmaFall = true;
                    }
                }
                else if (_waitingForSmaFall)
                {
                    if (!isHmaBelow)
                    {
                        _waitingForSmaFall = false;
                    }
                    else if (isSmaFalling)
                    {
                        TriggerSignal("SELL", "SMA Started Falling after HMA CrossDown (Delayed)");
                        _waitingForSmaFall = false;
                    }
                }
            }
            else
            {
                _waitingForSmaFall = false;
            }
        }

        private void TriggerSignal(string type, string reason)
        {
            int index = Bars.Count - 1;
            // Use converted Server Time to respect robot's TimeZone even in backtest.
            string localTime = TimeZoneInfo.ConvertTimeFromUtc(TimeInUtc, TimeZone).ToString("yyyy-MM-dd HH:mm:ss");

            if (type == "BUY")
            {
                Chart.DrawIcon("BuySignal_" + index, ChartIconType.UpArrow, index, Bars.LowPrices[index] - Symbol.PipSize * 5, Color.Green);
            }
            else if (type == "SELL")
            {
                Chart.DrawIcon("SellSignal_" + index, ChartIconType.DownArrow, index, Bars.HighPrices[index] + Symbol.PipSize * 5, Color.Red);
            }

            string logMessage = $"[{localTime}] {Symbol.Name} ({TimeFrame}) {type}: {reason}";
            Print(logMessage);

            // Suppress external notifications during backtesting.
            if (!IsBacktesting)
            {
                PlaySoundAlert();
                
                string emoji = (type == "BUY" ? "🟢" : (type == "SELL" ? "🔴" : "ℹ"));
                string htmlMessage = $"{emoji} <b>{Symbol.Name}</b> ({TimeFrame})\n" +
                                     $"<b>{type} Signal</b>\n" +
                                     $"Reason: <i>{reason}</i>\n" +
                                     $"Time: <code>{localTime}</code>";
                
                Task.Run(() => SendTelegramMessageAsync(htmlMessage));
            }
        }

        private void PlaySoundAlert()
        {
            try
            {
                if (!string.IsNullOrWhiteSpace(SoundFilePath))
                {
                    Notifications.PlaySound(SoundFilePath);
                }
            }
            catch (Exception ex)
            {
                Print("Error playing sound: {0}", ex.Message);
            }
        }

        private async Task SendTelegramMessageAsync(string message)
        {
            if (string.IsNullOrWhiteSpace(TelegramBotToken) || string.IsNullOrWhiteSpace(TelegramChatId))
            {
                return;
            }

            try
            {
                string url = $"https://api.telegram.org/bot{TelegramBotToken}/sendMessage?chat_id={TelegramChatId}&text={Uri.EscapeDataString(message)}&parse_mode=HTML";
                HttpResponseMessage response = await _httpClient.GetAsync(url);
                
                if (!response.IsSuccessStatusCode)
                {
                    Print("Telegram Error: {0}", response.StatusCode);
                }
            }
            catch (Exception ex)
            {
                Print("Exception sending Telegram message: {0}", ex.Message);
            }
        }
    }
}