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 ModernNumericUpDown : UserControl
    {
        private readonly TextBox _textBox;
        private readonly Panel _upButton;
        private readonly Panel _downButton;
        private ThemeColors _theme;
        private bool _hoverUp;
        private bool _hoverDown;
        private bool _focused;
        private decimal _value = 1m;
        private decimal _minimum = 1m;
        private decimal _maximum = 999m;

        public event EventHandler ValueChanged;

        public decimal Value
        {
            get => _value;
            set => SetValue(value, true);
        }

        public decimal Minimum
        {
            get => _minimum;
            set
            {
                _minimum = value;
                SetValue(_value, false);
            }
        }

        public decimal Maximum
        {
            get => _maximum;
            set
            {
                _maximum = value;
                SetValue(_value, false);
            }
        }

        public ModernNumericUpDown()
        {
            Width = 72;
            Height = 32;
            TabStop = true;
            SetStyle(ControlStyles.AllPaintingInWmPaint |
                     ControlStyles.UserPaint |
                     ControlStyles.OptimizedDoubleBuffer |
                     ControlStyles.ResizeRedraw, true);

            Padding = new Padding(6, 2, 0, 2);

            _textBox = new TextBox
            {
                BorderStyle = BorderStyle.None,
                TextAlign = HorizontalAlignment.Center,
                Dock = DockStyle.Fill,
                MaxLength = 4
            };
            _textBox.KeyPress += OnTextBoxKeyPress;
            _textBox.Leave += OnTextBoxLeave;
            _textBox.Enter += (_, __) => { _focused = true; Invalidate(); };
            _textBox.TextChanged += OnTextBoxTextChanged;

            _upButton = CreateStepButton(true);
            _downButton = CreateStepButton(false);

            var stepHost = new TableLayoutPanel
            {
                Width = 24,
                Dock = DockStyle.Right,
                ColumnCount = 1,
                RowCount = 2,
                Margin = new Padding(0, 1, 1, 1)
            };
            stepHost.RowStyles.Add(new RowStyle(SizeType.Percent, 50f));
            stepHost.RowStyles.Add(new RowStyle(SizeType.Percent, 50f));

            _upButton.Dock = DockStyle.Fill;
            _downButton.Dock = DockStyle.Fill;
            stepHost.Controls.Add(_upButton, 0, 0);
            stepHost.Controls.Add(_downButton, 0, 1);

            Controls.Add(stepHost);
            Controls.Add(_textBox);

            SetValue(1m, false);
        }

        public void ApplyTheme(ThemeColors theme)
        {
            _theme = theme;
            _textBox.Font = theme.FontRegular13;
            _textBox.BackColor = theme.InputBackground;
            _textBox.ForeColor = theme.TextPrimary;
            Invalidate();
        }

        private Panel CreateStepButton(bool isUp)
        {
            var button = new Panel
            {
                Cursor = Cursors.Hand,
                TabStop = false
            };

            button.Paint += (_, e) => PaintStepButton(e.Graphics, button.ClientRectangle, isUp);
            button.MouseEnter += (_, __) =>
            {
                if (isUp) _hoverUp = true;
                else _hoverDown = true;
                Invalidate();
            };
            button.MouseLeave += (_, __) =>
            {
                if (isUp) _hoverUp = false;
                else _hoverDown = false;
                Invalidate();
            };
            button.Click += (_, __) =>
            {
                SetValue(_value + (isUp ? 1m : -1m), true);
                Focus();
            };
            return button;
        }

        private void PaintStepButton(Graphics g, Rectangle bounds, bool isUp)
        {
            var theme = _theme ?? ThemeManager.Colors;
            var hover = isUp ? _hoverUp : _hoverDown;
            var fill = hover ? theme.AccentSecondary : theme.InputBackground;
            using (var brush = new SolidBrush(fill))
            {
                g.FillRectangle(brush, bounds);
            }

            var arrowColor = hover ? theme.AccentPrimary : theme.TextMuted;
            var centerX = bounds.X + (bounds.Width / 2f);
            var centerY = bounds.Y + (bounds.Height / 2f);
            var size = 3f;
            using (var pen = new Pen(arrowColor, 1.6f))
            {
                pen.StartCap = LineCap.Round;
                pen.EndCap = LineCap.Round;
                if (isUp)
                {
                    g.DrawLine(pen, centerX - size, centerY + 1, centerX, centerY - 1);
                    g.DrawLine(pen, centerX, centerY - 1, centerX + size, centerY + 1);
                }
                else
                {
                    g.DrawLine(pen, centerX - size, centerY - 1, centerX, centerY + 1);
                    g.DrawLine(pen, centerX, centerY + 1, centerX + size, centerY - 1);
                }
            }
        }

        private void OnTextBoxKeyPress(object sender, KeyPressEventArgs e)
        {
            if (char.IsControl(e.KeyChar))
            {
                return;
            }

            if (!char.IsDigit(e.KeyChar))
            {
                e.Handled = true;
            }
        }

        private void OnTextBoxTextChanged(object sender, EventArgs e)
        {
            if (!_textBox.Focused)
            {
                return;
            }
        }

        private void OnTextBoxLeave(object sender, EventArgs e)
        {
            _focused = false;
            if (decimal.TryParse(_textBox.Text, out var parsed))
            {
                SetValue(parsed, true);
            }
            else
            {
                _textBox.Text = ((int)_value).ToString();
            }

            Invalidate();
        }

        private void SetValue(decimal value, bool notify)
        {
            var clamped = Math.Max(_minimum, Math.Min(_maximum, decimal.Truncate(value)));
            var changed = clamped != _value;
            _value = clamped;
            _textBox.Text = ((int)_value).ToString();

            if (notify && changed)
            {
                ValueChanged?.Invoke(this, EventArgs.Empty);
            }
        }

        protected override void OnPaintBackground(PaintEventArgs e)
        {
        }

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

            var bounds = new Rectangle(0, 0, Width - 1, Height - 1);
            var radius = theme.CornerRadiusSmall;
            using (var fill = new SolidBrush(theme.InputBackground))
            {
                GraphicsExtensions.FillRoundedRectangle(g, fill, bounds, radius);
            }

            var borderColor = _focused ? theme.InputBorderFocus : theme.InputBorder;
            using (var pen = new Pen(borderColor, _focused ? 1.5f : 1f))
            {
                GraphicsExtensions.DrawRoundedRectangle(g, pen, bounds, radius);
            }

            var dividerX = Width - 25;
            using (var divider = new Pen(theme.InputBorder))
            {
                g.DrawLine(divider, dividerX, 6, dividerX, Height - 7);
            }

            _upButton.Invalidate();
            _downButton.Invalidate();
        }

        protected override void OnGotFocus(EventArgs e)
        {
            base.OnGotFocus(e);
            _textBox.Focus();
        }
    }
}
