using System;
using cAlgo.API;
using cAlgo.API.Internals;

namespace cAlgo
{
    [Indicator(IsOverlay = true, TimeZone = TimeZones.UTC, AccessRights = AccessRights.None)]
    public class ImbalanceAlert : Indicator
    {
        #region Parameters

        // Alert Settings
        [Parameter("Send Email", DefaultValue = true, Group = "Alert Settings")]
        public bool SendEmail { get; set; }

        [Parameter("Sender Email", DefaultValue = "junk001@mycelium.de", Group = "Alert Settings")]
        public string SenderEmail { get; set; }

        [Parameter("Recipient Email", DefaultValue = "junk001@mycelium.de", Group = "Alert Settings")]
        public string RecipientEmail { get; set; }

        [Parameter("Play Sound", DefaultValue = true, Group = "Alert Settings")]
        public bool PlaySound { get; set; }

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

        // Filters
        [Parameter("Min Gap Size (Pips)", DefaultValue = 1.0, Group = "Filters")]
        public double MinGapSizePips { get; set; }

        // Visuals
        [Parameter("Draw Boxes", DefaultValue = true, Group = "Visuals")]
        public bool DrawBoxes { get; set; }

        [Parameter("Bullish Color", DefaultValue = "Green", Group = "Visuals")]
        public string BullishColorName { get; set; }

        [Parameter("Bearish Color", DefaultValue = "Red", Group = "Visuals")]
        public string BearishColorName { get; set; }

        #endregion

        #region Fields

        private int _lastAlertBarIndex = -1;
        private Color _bullColor;
        private Color _bearColor;

        #endregion

        protected override void Initialize()
        {
            // 50% Transparency (Alpha 127 out of 255)
            _bullColor = Color.FromArgb(127, Color.FromName(BullishColorName));
            _bearColor = Color.FromArgb(127, Color.FromName(BearishColorName));
        }

        public override void Calculate(int index)
        {
            // Need at least 3 completed bars (index-3 to index-1)
            if (index < 3) return;

            int cIndex = index - 1; // The closed bar confirming the gap
            int aIndex = index - 3; // The origin bar

            double highA = Bars.HighPrices[aIndex];
            double lowA = Bars.LowPrices[aIndex];
            
            double highC = Bars.HighPrices[cIndex];
            double lowC = Bars.LowPrices[cIndex];

            // Check Bullish FVG (Undervalued)
            // Gap is between High of A and Low of C
            if (lowC > highA)
            {
                // Bottom: HighA, Top: LowC
                ProcessGap(true, aIndex, cIndex, highA, lowC, index);
            }
            // Check Bearish FVG (Overvalued)
            // Gap is between Low of A and High of C
            else if (highC < lowA)
            {
                // Bottom: HighC, Top: LowA (Bugfix: Parameter order swapped)
                ProcessGap(false, aIndex, cIndex, highC, lowA, index);
            }
        }

        private void ProcessGap(bool isBullish, int startBarIdx, int endBarIdx, double bottomPrice, double topPrice, int currentIndex)
        {
            double gapSize = topPrice - bottomPrice;
            
            // Check against min size
            if (gapSize < MinGapSizePips * Symbol.PipSize) return;

            // Visualization
            if (DrawBoxes)
            {
                string objName = $"FVG_{startBarIdx}";
                var color = isBullish ? _bullColor : _bearColor;
                
                // Draw rectangle
                var rect = Chart.DrawRectangle(objName, startBarIdx, bottomPrice, endBarIdx, topPrice, color, 1, LineStyle.Solid);
                rect.IsFilled = true;
            }

            // Alert Logic
            if (IsLastBar && RunningMode == RunningMode.RealTime)
            {
                if (_lastAlertBarIndex != currentIndex)
                {
                    TriggerAlerts(isBullish, topPrice, bottomPrice);
                    _lastAlertBarIndex = currentIndex;
                }
            }
        }

        private void TriggerAlerts(bool isBullish, double top, double bottom)
        {
            string type = isBullish ? "BULLISH" : "BEARISH";
            string message = $"{Symbol.Name} ({TimeFrame}): {type} Imbalance Detected. Range: {bottom} - {top}";

            // 1. Sound Alert
            if (PlaySound)
            {
                if (!string.IsNullOrWhiteSpace(SoundFilePath))
                {
                    try 
                    {
                        Notifications.PlaySound(SoundFilePath);
                    }
                    catch
                    {
                        Notifications.PlaySound(SoundType.Doorbell);
                    }
                }
            }

            // 2. Email Alert
            if (SendEmail)
            {
                SendAlertEmail(type, top, bottom);
            }
            
            Print(message);
        }

        private void SendAlertEmail(string type, double top, double bottom)
        {
            try
            {
                string subject = $"{Symbol.Name} ({TimeFrame}): {type} Imbalance Detected";
                string body = $@"
                    <h1>Imbalance Manifested</h1>
                    <p><strong>Symbol:</strong> {Symbol.Name}</p>
                    <p><strong>Timeframe:</strong> {TimeFrame}</p>
                    <p><strong>Direction:</strong> {type}</p>
                    <p><strong>Gap Range:</strong> {bottom} - {top}</p>
                    <p><strong>Time:</strong> {Server.Time.ToUniversalTime()} UTC</p>
                ";

                Notifications.SendEmail(SenderEmail, RecipientEmail, subject, body);
            }
            catch (Exception ex)
            {
                Print($"Failed to send email: {ex.Message}");
            }
        }
    }
}