using System;
using System.Drawing;
using System.Drawing.Drawing2D;
using System.Windows.Forms;
using Elfisa.UI.Helpers;
using Elfisa.UI.Theming;

namespace Elfisa.UI.Controls
{
    public class ModernButton : Button
    {
        private bool _hover;
        private bool _pressed;
        private float _hoverAnim;
        private ThemeColors _theme;
        private ModernButtonStyle _buttonStyle = ModernButtonStyle.Primary;
        private bool _sidebarMode;
        private bool _topNavMode;
        private bool _headerNavMode;
        private bool _isActiveItem;
        private string _navIconGlyph;
        private string _iconGlyph;
        private bool _compactIconMode;
        private bool _focused;
        private bool _allowTextEllipsis = true;
        private readonly AnimationTimer _animTimer;

        public bool CompactIconMode
        {
            get => _compactIconMode;
            set
            {
                _compactIconMode = value;
                Invalidate();
            }
        }

        public bool AllowTextEllipsis
        {
            get => _allowTextEllipsis;
            set => _allowTextEllipsis = value;
        }

        public string IconGlyph
        {
            get => _iconGlyph;
            set { _iconGlyph = value; Invalidate(); }
        }

        public bool HeaderNavMode
        {
            get => _headerNavMode;
            set { _headerNavMode = value; Invalidate(); }
        }

        public string NavIconGlyph
        {
            get => _navIconGlyph;
            set { _navIconGlyph = value; Invalidate(); }
        }

        public bool TopNavMode
        {
            get => _topNavMode;
            set { _topNavMode = value; Invalidate(); }
        }

        public bool SidebarMode
        {
            get => _sidebarMode;
            set { _sidebarMode = value; Invalidate(); }
        }

        public bool IsActiveItem
        {
            get => _isActiveItem;
            set { _isActiveItem = value; Invalidate(); }
        }

        public ModernButtonStyle ButtonStyle
        {
            get => _buttonStyle;
            set
            {
                _buttonStyle = value;
                ApplyRoundedRegion();
                Invalidate();
            }
        }

        protected override void OnPaintBackground(PaintEventArgs pevent)
        {
            if (_headerNavMode || _topNavMode)
            {
                return;
            }

            using (var brush = new SolidBrush(ResolveChromeBackground()))
            {
                pevent.Graphics.FillRectangle(brush, ClientRectangle);
            }
        }

        private Color ResolveChromeBackground()
        {
            var theme = _theme ?? ThemeManager.Colors;
            var parentTag = Parent?.Tag as string;
            if (parentTag == "toolbar")
            {
                return theme.ToolbarBackground;
            }

            if (parentTag == "chrome-child" || parentTag == "status-footer")
            {
                return theme.BackgroundSecondary;
            }

            var current = Parent;
            while (current != null)
            {
                if (current.Tag as string == "keep-bg")
                {
                    current = current.Parent;
                    continue;
                }

                var backColor = current.BackColor;
                if (backColor.A > 0 && backColor != Color.Transparent)
                {
                    return backColor;
                }

                current = current.Parent;
            }

            return theme.Surface;
        }

        private int GetCornerRadius()
        {
            if (_headerNavMode || _topNavMode || _sidebarMode)
            {
                return 0;
            }

            if (SkillGradientButtonPaint.UsesGradient(_buttonStyle, _compactIconMode))
            {
                return SkillGradientButtonPaint.GetCornerRadius(_buttonStyle, _compactIconMode);
            }

            return 6;
        }

        private void ApplyRoundedRegion()
        {
            var radius = GetCornerRadius();
            if (radius <= 0 || Width <= 0 || Height <= 0)
            {
                Region = null;
                return;
            }

            var bounds = new Rectangle(0, 0, Width, Height);
            using (var path = GraphicsExtensions.CreateRoundedRectangle(bounds, radius))
            {
                Region = new Region(path);
            }
        }

        public ModernButton()
        {
            SetStyle(ControlStyles.AllPaintingInWmPaint |
                     ControlStyles.UserPaint |
                     ControlStyles.OptimizedDoubleBuffer |
                     ControlStyles.ResizeRedraw, true);
            FlatStyle = FlatStyle.Flat;
            FlatAppearance.BorderSize = 0;
            Cursor = Cursors.Hand;
            Font = new Font("Segoe UI Semibold", 10f, FontStyle.Bold);
            Height = ModernButtonStyles.DefaultHeight;
            MinimumSize = new Size(72, ModernButtonStyles.DefaultHeight);
            Padding = new Padding(16, 6, 16, 6);
            TabStop = true;
            _animTimer = new AnimationTimer(v => { _hoverAnim = v; Invalidate(); });
        }

        public void ApplyTheme(ThemeColors theme)
        {
            _theme = theme;
            if (_headerNavMode)
            {
                Font = new Font("Segoe UI", 11f, FontStyle.Bold);
            }
            else if (_compactIconMode)
            {
                Font = new Font("Segoe UI Semibold", 13f, FontStyle.Bold);
            }
            else
            {
                Font = theme.FontSemibold14 != null
                    ? new Font(theme.FontSemibold14.FontFamily, 10f, FontStyle.Bold)
                    : new Font("Segoe UI Semibold", 10f, FontStyle.Bold);
            }

            if (SkillGradientButtonPaint.UsesGradient(_buttonStyle, _compactIconMode) && !_headerNavMode && !_topNavMode)
            {
                BackColor = ResolveChromeBackground();
            }

            ApplyRoundedRegion();
            Invalidate();
        }

        protected override void OnMouseEnter(EventArgs e)
        {
            _hover = true;
            _animTimer.AnimateTo(1f);
            Invalidate();
            base.OnMouseEnter(e);
        }

        protected override void OnMouseLeave(EventArgs e)
        {
            _hover = false;
            _pressed = false;
            _animTimer.AnimateTo(0f);
            Invalidate();
            base.OnMouseLeave(e);
        }

        protected override void OnMouseDown(MouseEventArgs mevent)
        {
            if (mevent.Button == MouseButtons.Left)
            {
                _pressed = true;
                Invalidate();
            }
            base.OnMouseDown(mevent);
        }

        protected override void OnMouseUp(MouseEventArgs mevent)
        {
            _pressed = false;
            Invalidate();
            base.OnMouseUp(mevent);
        }

        protected override void OnEnabledChanged(EventArgs e)
        {
            Invalidate();
            base.OnEnabledChanged(e);
        }

        protected override void OnHandleCreated(EventArgs e)
        {
            base.OnHandleCreated(e);
            ApplyRoundedRegion();
        }

        protected override void OnResize(EventArgs e)
        {
            base.OnResize(e);
            ApplyRoundedRegion();
        }

        protected override void OnParentChanged(EventArgs e)
        {
            base.OnParentChanged(e);
            ApplyRoundedRegion();
            Invalidate();
        }

        protected override void OnGotFocus(EventArgs e)
        {
            _focused = true;
            Invalidate();
            base.OnGotFocus(e);
        }

        protected override void OnLostFocus(EventArgs e)
        {
            _focused = false;
            Invalidate();
            base.OnLostFocus(e);
        }

        protected override void Dispose(bool disposing)
        {
            if (disposing)
            {
                _animTimer.Dispose();
            }
            base.Dispose(disposing);
        }

        protected override void OnPaint(PaintEventArgs pevent)
        {
            var theme = _theme ?? ThemeManager.Colors;
            var g = pevent.Graphics;
            g.SmoothingMode = SmoothingMode.AntiAlias;
            g.PixelOffsetMode = PixelOffsetMode.HighQuality;
            g.CompositingQuality = CompositingQuality.HighQuality;
            g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit;

            var bounds = new Rectangle(0, 0, Width, Height);
            var usesGradient = SkillGradientButtonPaint.UsesGradient(_buttonStyle, _compactIconMode);

            if (!_headerNavMode && !_topNavMode && !_sidebarMode)
            {
                using (var bgBrush = new SolidBrush(ResolveChromeBackground()))
                {
                    g.FillRectangle(bgBrush, bounds);
                }
            }

            if (_headerNavMode)
            {
                var headerBounds = new Rectangle(0, 0, Width - 1, Height - 1);
                var headerRadius = theme.CornerRadiusSmall;
                var activeBoost = _isActiveItem ? 0.22f : 0.06f;
                var hoverBoost = _hoverAnim * 0.14f;
                var alpha = (int)(255 * (activeBoost + hoverBoost));
                var headerFill = Color.FromArgb(alpha, 255, 255, 255);
                using (var brush = new SolidBrush(headerFill))
                {
                    GraphicsExtensions.FillRoundedRectangle(g, brush, headerBounds, headerRadius);
                }

                if (_isActiveItem)
                {
                    using (var pen = new Pen(Color.FromArgb(180, 255, 255, 255), 1f))
                    {
                        GraphicsExtensions.DrawRoundedRectangle(g, pen, headerBounds, headerRadius);
                    }
                }

                DrawHeaderNavContent(g, headerBounds, theme);
                return;
            }

            if (usesGradient && !_topNavMode && !_sidebarMode)
            {
                SkillGradientButtonPaint.Paint(
                    g,
                    bounds,
                    _buttonStyle,
                    _compactIconMode,
                    _hover && Enabled,
                    _pressed && Enabled,
                    Enabled);

                var contentRect = SkillGradientButtonPaint.GetContentRect(
                    bounds,
                    _buttonStyle,
                    _compactIconMode,
                    Enabled);

                var gradientTextColor = Enabled ? theme.TextOnAccent : theme.TextMuted;
                DrawActionButtonContent(g, contentRect, gradientTextColor);
                return;
            }

            var flatBounds = new Rectangle(0, 0, Width - 1, Height - 1);
            var radius = GetCornerRadius();
            var baseColor = ResolveBaseColor(theme);
            var fill = baseColor;

            if (_topNavMode)
            {
                fill = Color.Transparent;
            }
            else if (_sidebarMode)
            {
                fill = _isActiveItem ? theme.SidebarItemActive : theme.SidebarBackground;
                if (_hover && !_isActiveItem)
                {
                    fill = theme.SidebarItemHover;
                }
            }
            else if (_buttonStyle == ModernButtonStyle.Subtle)
            {
                fill = Color.Transparent;
                if (!Enabled)
                {
                    fill = Color.Transparent;
                }
                else if (_pressed)
                {
                    fill = GraphicsExtensions.Blend(theme.GridRowHover, theme.BorderSubtle, 0.35f);
                }
                else if (_hover)
                {
                    fill = GraphicsExtensions.Blend(theme.GridRowHover, Color.Transparent, 1f - (_hoverAnim * 0.65f));
                }
            }
            else if (!Enabled)
            {
                fill = ApplyDisabledFill(theme, baseColor);
            }
            else if (_pressed)
            {
                fill = ResolvePressedColor(theme, baseColor);
            }
            else if (_hover)
            {
                fill = GraphicsExtensions.Blend(
                    ResolveHoverColor(theme, baseColor),
                    baseColor,
                    1f - (_hoverAnim * 0.45f));
            }

            if (!_topNavMode && fill.A > 0)
            {
                using (var brush = new SolidBrush(fill))
                {
                    GraphicsExtensions.FillRoundedRectangle(g, brush, flatBounds, radius);
                }
            }

            if (_topNavMode)
            {
                if (_isActiveItem)
                {
                    using (var pen = new Pen(theme.AccentPrimary, 2f))
                    {
                        g.DrawLine(pen, 0, Height - 2, Width, Height - 2);
                    }
                }
                else if (_hover)
                {
                    using (var pen = new Pen(theme.Border, 1f))
                    {
                        g.DrawLine(pen, 0, Height - 1, Width, Height - 1);
                    }
                }
            }
            else if ((_buttonStyle == ModernButtonStyle.Secondary
                      || _buttonStyle == ModernButtonStyle.DangerSoft
                      || _buttonStyle == ModernButtonStyle.Subtle) && !_sidebarMode && !_compactIconMode)
            {
                if (_buttonStyle == ModernButtonStyle.Subtle && !_hover && !_pressed && !_focused)
                {
                    // WinUI SubtleButton — no border at rest.
                }
                else
                {
                    var borderColor = _buttonStyle == ModernButtonStyle.DangerSoft
                        ? GraphicsExtensions.Blend(theme.Danger, Color.White, 0.45f)
                        : _buttonStyle == ModernButtonStyle.Subtle
                        ? theme.Border
                        : theme.InputBorder;
                    if (_hover && Enabled)
                    {
                        borderColor = _buttonStyle == ModernButtonStyle.DangerSoft
                            ? theme.Danger
                            : theme.InputBorderFocus;
                    }

                    using (var pen = new Pen(borderColor, 1f))
                    {
                        GraphicsExtensions.DrawRoundedRectangle(g, pen, flatBounds, radius);
                    }
                }
            }

            if (_focused && Enabled && ShowFocusCues && !_headerNavMode && !_topNavMode && !_sidebarMode && !_compactIconMode)
            {
                var focusBounds = Rectangle.Inflate(flatBounds, -2, -2);
                using (var pen = new Pen(theme.InputBorderFocus, 2f))
                {
                    GraphicsExtensions.DrawRoundedRectangle(g, pen, focusBounds, Math.Max(2, radius - 1));
                }
            }

            var textColor = _topNavMode
                ? (_isActiveItem ? theme.AccentPrimary : theme.TextMuted)
                : _sidebarMode
                ? (_isActiveItem ? theme.SidebarItemActiveText : theme.SidebarItem)
                : _buttonStyle == ModernButtonStyle.DangerSoft
                ? theme.Danger
                : _buttonStyle == ModernButtonStyle.Subtle
                ? theme.TextPrimary
                : _buttonStyle == ModernButtonStyle.Secondary
                ? theme.TextPrimary
                : theme.TextOnAccent;

            if (_buttonStyle == ModernButtonStyle.Warning)
            {
                textColor = Color.FromArgb(40, 40, 40);
            }

            if (!Enabled)
            {
                textColor = GraphicsExtensions.Blend(textColor, theme.TextMuted, 0.55f);
            }

            DrawActionButtonContent(g, flatBounds, textColor);
        }

        private void DrawActionButtonContent(Graphics g, Rectangle bounds, Color textColor)
        {
            if (_compactIconMode)
            {
                var textBounds = bounds;
                if (Text == "×")
                {
                    textBounds.Offset(1, -2);
                }

                TextRenderer.DrawText(
                    g,
                    Text,
                    Font,
                    textBounds,
                    textColor,
                    TextFormatFlags.HorizontalCenter | TextFormatFlags.VerticalCenter | TextFormatFlags.SingleLine);
                return;
            }

            var horizontalPad = Math.Max(Padding.Left, Padding.Right);
            if (horizontalPad < 12)
            {
                horizontalPad = 12;
            }

            var hasIcon = !string.IsNullOrEmpty(_iconGlyph);
            var iconWidth = hasIcon ? 22 : 0;
            var gap = hasIcon ? 6 : 0;
            var innerWidth = Math.Max(0, bounds.Width - (horizontalPad * 2));
            var textSize = TextRenderer.MeasureText(
                g,
                Text,
                Font,
                new Size(innerWidth, bounds.Height),
                TextFormatFlags.SingleLine | TextFormatFlags.EndEllipsis);

            if (hasIcon)
            {
                var contentWidth = iconWidth + gap + textSize.Width;
                var startX = _topNavMode
                    ? bounds.X + horizontalPad
                    : bounds.X + horizontalPad + Math.Max(0, (innerWidth - contentWidth) / 2);

                using (var iconFont = FluentFonts.CreateIconFont(13f))
                {
                    var iconRect = new Rectangle(startX, bounds.Y, iconWidth, bounds.Height);
                    TextRenderer.DrawText(
                        g,
                        _iconGlyph,
                        iconFont,
                        iconRect,
                        textColor,
                        TextFormatFlags.VerticalCenter | TextFormatFlags.HorizontalCenter | TextFormatFlags.SingleLine);
                }

                startX += iconWidth + gap;
                var textRect = new Rectangle(
                    startX,
                    bounds.Y,
                    Math.Max(0, bounds.Right - horizontalPad - startX),
                    bounds.Height);
                TextRenderer.DrawText(
                    g,
                    Text,
                    Font,
                    textRect,
                    textColor,
                    TextFormatFlags.VerticalCenter | TextFormatFlags.Left | TextFormatFlags.SingleLine | TextFormatFlags.EndEllipsis);
                return;
            }

            var contentRect = new Rectangle(
                bounds.X + horizontalPad,
                bounds.Y,
                innerWidth,
                bounds.Height);
            var textFlags = TextFormatFlags.VerticalCenter | TextFormatFlags.SingleLine;
            if (_allowTextEllipsis)
            {
                textFlags |= TextFormatFlags.EndEllipsis;
            }
            textFlags |= _topNavMode ? TextFormatFlags.Left : TextFormatFlags.HorizontalCenter;
            TextRenderer.DrawText(g, Text, Font, contentRect, textColor, textFlags);
        }

        private void DrawHeaderNavContent(Graphics g, Rectangle bounds, ThemeColors theme)
        {
            using (var iconFont = FluentFonts.CreateIconFont(18f))
            {
                var textColor = Color.White;
                var iconRect = new Rectangle(bounds.X, bounds.Y + 8, bounds.Width, 28);
                var textRect = new Rectangle(bounds.X, bounds.Y + 34, bounds.Width, bounds.Height - 34);

                if (!string.IsNullOrEmpty(_navIconGlyph))
                {
                    TextRenderer.DrawText(
                        g,
                        _navIconGlyph,
                        iconFont,
                        iconRect,
                        textColor,
                        TextFormatFlags.HorizontalCenter | TextFormatFlags.VerticalCenter | TextFormatFlags.SingleLine);
                }

                TextRenderer.DrawText(
                    g,
                    Text,
                    Font,
                    textRect,
                    textColor,
                    TextFormatFlags.HorizontalCenter | TextFormatFlags.VerticalCenter | TextFormatFlags.SingleLine);
            }
        }

        private static Color ApplyDisabledFill(ThemeColors theme, Color baseColor)
        {
            if (baseColor == theme.Surface || baseColor == theme.DangerSoft)
            {
                return GraphicsExtensions.Blend(baseColor, theme.BorderSubtle, 0.35f);
            }

            return GraphicsExtensions.Blend(baseColor, theme.BorderSubtle, 0.55f);
        }

        private Color ResolveBaseColor(ThemeColors theme)
        {
            switch (_buttonStyle)
            {
                case ModernButtonStyle.Secondary: return theme.Surface;
                case ModernButtonStyle.Subtle: return Color.Transparent;
                case ModernButtonStyle.Success: return theme.Success;
                case ModernButtonStyle.Warning: return theme.Warning;
                case ModernButtonStyle.Danger: return theme.Danger;
                case ModernButtonStyle.DangerSoft: return theme.DangerSoft;
                default: return theme.AccentPrimary;
            }
        }

        private static Color ResolveHoverColor(ThemeColors theme, Color baseColor)
        {
            if (baseColor == theme.AccentPrimary) return theme.AccentPrimaryHover;
            if (baseColor == theme.Surface) return theme.GridRowHover;
            if (baseColor == theme.DangerSoft) return GraphicsExtensions.Blend(theme.DangerSoft, theme.Danger, 0.08f);
            if (baseColor == theme.Danger) return GraphicsExtensions.Blend(theme.Danger, Color.White, 0.08f);
            if (baseColor == theme.Success) return GraphicsExtensions.Blend(theme.Success, Color.White, 0.12f);
            if (baseColor == theme.Warning) return GraphicsExtensions.Blend(theme.Warning, Color.White, 0.12f);
            return GraphicsExtensions.Blend(baseColor, Color.White, 0.08f);
        }

        private static Color ResolvePressedColor(ThemeColors theme, Color baseColor)
        {
            if (baseColor == theme.AccentPrimary) return theme.AccentPrimaryPressed;
            return GraphicsExtensions.Blend(baseColor, Color.Black, 0.12f);
        }
    }
}
