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

namespace Elfisa.UI.Controls
{
    /// <summary>
    /// Вкладки в стиле документных. Контент показывается в Panel — без системной рамки TabControl.
    /// </summary>
    public class ModernTabControl : UserControl
    {
        private const int StripHeight = 40;
        private const int TabTop = 6;
        private const int TabHeight = 28;
        private const int MinTabWidth = 120;
        private const int TabGap = 8;
        private const int ContentOverlap = 2;
        private const int FramePadding = 1;

        private readonly TabControl _inner;
        private readonly Panel _contentFrame;
        private readonly Panel _contentHost;
        private readonly Panel _strip;
        private readonly List<Rectangle> _tabHitAreas = new List<Rectangle>();
        private ThemeColors _theme;
        private int _hoverIndex = -1;
        private TabPage _displayedPage;
        private bool _isReparenting;

        public TabControl.TabPageCollection TabPages => _inner.TabPages;

        public int SelectedIndex
        {
            get => _inner.SelectedIndex;
            set => _inner.SelectedIndex = value;
        }

        public int TabCount => _inner.TabCount;

        public ModernTabControl()
        {
            SetStyle(ControlStyles.AllPaintingInWmPaint |
                     ControlStyles.OptimizedDoubleBuffer |
                     ControlStyles.ResizeRedraw, true);

            _inner = new TabControl
            {
                Visible = false,
                Size = new Size(0, 0),
                TabStop = false,
                Tag = "keep-bg"
            };
            _inner.SelectedIndexChanged += (_, __) =>
            {
                DisplaySelectedTab();
                _strip.Invalidate();
            };
            _inner.ControlAdded += OnInnerControlAdded;
            _inner.ControlRemoved += OnInnerControlRemoved;

            _contentHost = new Panel
            {
                Dock = DockStyle.Fill,
                Tag = "keep-bg"
            };

            _contentFrame = new Panel
            {
                Dock = DockStyle.Fill,
                Padding = new Padding(FramePadding),
                Tag = "keep-bg"
            };
            _contentFrame.Controls.Add(_contentHost);

            _strip = new Panel
            {
                Dock = DockStyle.Top,
                Height = StripHeight,
                Tag = "keep-bg"
            };
            _strip.Paint += OnStripPaint;
            _strip.MouseMove += OnStripMouseMove;
            _strip.MouseLeave += OnStripMouseLeave;
            _strip.MouseClick += OnStripMouseClick;

            Controls.Add(_inner);
            Controls.Add(_contentFrame);
            Controls.Add(_strip);
        }

        public void SelectTab(TabPage page)
        {
            var index = _inner.TabPages.IndexOf(page);
            if (index < 0)
            {
                return;
            }

            if (_inner.SelectedIndex == index)
            {
                DisplaySelectedTab();
            }
            else
            {
                _inner.SelectedIndex = index;
            }
        }

        public void ApplyTheme(ThemeColors theme)
        {
            _theme = theme;
            BackColor = theme.BackgroundSecondary;
            _strip.BackColor = theme.BackgroundSecondary;
            _contentFrame.BackColor = theme.Border;
            _contentHost.BackColor = theme.BackgroundPrimary;
            SyncTabPageTheme();
            _strip.Invalidate();
        }

        private void OnInnerControlAdded(object sender, ControlEventArgs e)
        {
            SyncTabPageTheme();
            _strip.Invalidate();
        }

        private void OnInnerControlRemoved(object sender, ControlEventArgs e)
        {
            if (e.Control is TabPage page && page == _displayedPage)
            {
                _displayedPage = null;
            }

            if (_inner.TabCount == 0)
            {
                _displayedPage = null;
                _contentHost.Controls.Clear();
            }

            _strip.Invalidate();
        }

        private void DisplaySelectedTab()
        {
            if (_isReparenting)
            {
                return;
            }

            _isReparenting = true;
            try
            {
                ReturnControlsToTabPage(_displayedPage);

                if (_inner.SelectedIndex < 0 || _inner.SelectedIndex >= _inner.TabCount)
                {
                    _displayedPage = null;
                    _contentHost.Controls.Clear();
                    return;
                }

                _displayedPage = _inner.TabPages[_inner.SelectedIndex];
                MoveControlsToHost(_displayedPage);
            }
            finally
            {
                _isReparenting = false;
            }
        }

        private void ReturnControlsToTabPage(TabPage page)
        {
            if (page == null)
            {
                return;
            }

            var controls = new Control[_contentHost.Controls.Count];
            _contentHost.Controls.CopyTo(controls, 0);
            _contentHost.Controls.Clear();

            foreach (var control in controls)
            {
                control.Dock = DockStyle.Fill;
                page.Controls.Add(control);
            }
        }

        private void MoveControlsToHost(TabPage page)
        {
            _contentHost.Controls.Clear();

            var controls = new Control[page.Controls.Count];
            page.Controls.CopyTo(controls, 0);
            page.Controls.Clear();

            foreach (var control in controls)
            {
                control.Dock = DockStyle.Fill;
                _contentHost.Controls.Add(control);
            }
        }

        private void OnStripPaint(object sender, PaintEventArgs e)
        {
            var theme = _theme ?? ThemeManager.Colors;
            var g = e.Graphics;
            g.SmoothingMode = SmoothingMode.AntiAlias;
            g.TextRenderingHint = System.Drawing.Text.TextRenderingHint.ClearTypeGridFit;

            using (var bgBrush = new SolidBrush(theme.BackgroundSecondary))
            {
                g.FillRectangle(bgBrush, _strip.ClientRectangle);
            }

            _tabHitAreas.Clear();
            if (_inner.TabCount == 0)
            {
                DrawStripSeparator(g, theme, null, _strip.Width);
                return;
            }

            var x = 10;
            Rectangle? activeRect = null;
            using (var textFont = theme.FontSemibold14 ?? new Font("Segoe UI", 10f, FontStyle.Bold))
            {
                for (var i = 0; i < _inner.TabCount; i++)
                {
                    var page = _inner.TabPages[i];
                    var textSize = TextRenderer.MeasureText(page.Text, textFont);
                    var tabWidth = Math.Max(MinTabWidth, textSize.Width + 28);
                    var tabRect = new Rectangle(x, TabTop, tabWidth, TabHeight);
                    _tabHitAreas.Add(tabRect);

                    var isActive = _inner.SelectedIndex == i;
                    var isHover = _hoverIndex == i;

                    if (isActive)
                    {
                        activeRect = new Rectangle(x, TabTop, tabWidth, StripHeight - TabTop + ContentOverlap);
                    }
                    else
                    {
                        var backColor = theme.Surface;
                        if (isHover)
                        {
                            backColor = GraphicsExtensions.Blend(backColor, theme.AccentPrimarySoft, 0.35f);
                        }

                        using (var brush = new SolidBrush(backColor))
                        {
                            GraphicsExtensions.FillRoundedRectangle(g, brush, tabRect, theme.CornerRadiusSmall);
                        }

                        using (var pen = new Pen(theme.BorderSubtle))
                        {
                            GraphicsExtensions.DrawRoundedRectangle(g, pen, tabRect, theme.CornerRadiusSmall);
                        }

                        TextRenderer.DrawText(
                            g,
                            page.Text,
                            textFont,
                            tabRect,
                            theme.TextSecondary,
                            TextFormatFlags.HorizontalCenter | TextFormatFlags.VerticalCenter | TextFormatFlags.SingleLine | TextFormatFlags.EndEllipsis);
                    }

                    x += tabWidth + TabGap;
                }
            }

            if (activeRect.HasValue)
            {
                var rect = activeRect.Value;
                using (var brush = new SolidBrush(theme.BackgroundPrimary))
                {
                    GraphicsExtensions.FillTopRoundedRectangle(g, brush, rect, theme.CornerRadiusSmall);
                }

                var outlineColor = theme.Mode == ThemeMode.Dark ? theme.BorderSubtle : theme.AccentPrimaryBorder;
                using (var pen = new Pen(outlineColor, 1f))
                {
                    GraphicsExtensions.DrawAttachedTabOutline(g, pen, rect, theme.CornerRadiusSmall);
                }

                using (var seam = new SolidBrush(theme.BackgroundPrimary))
                {
                    g.FillRectangle(seam, rect.Left, StripHeight - ContentOverlap - 1, rect.Width, ContentOverlap + 2);
                }

                using (var textFont = theme.FontSemibold14 ?? new Font("Segoe UI", 10f, FontStyle.Bold))
                {
                    var textRect = new Rectangle(rect.X, TabTop, rect.Width, TabHeight);
                    TextRenderer.DrawText(
                        g,
                        _inner.TabPages[_inner.SelectedIndex].Text,
                        textFont,
                        textRect,
                        theme.TextPrimary,
                        TextFormatFlags.HorizontalCenter | TextFormatFlags.VerticalCenter | TextFormatFlags.SingleLine | TextFormatFlags.EndEllipsis);
                }
            }

            DrawStripSeparator(g, theme, activeRect, _strip.Width);
        }

        private static void DrawStripSeparator(Graphics g, ThemeColors theme, Rectangle? activeRect, int width)
        {
            var y = StripHeight - 1;
            using (var separator = new Pen(theme.Border))
            {
                if (activeRect.HasValue)
                {
                    var rect = activeRect.Value;
                    if (rect.Left > 0)
                    {
                        g.DrawLine(separator, 0, y, rect.Left, y);
                    }

                    if (rect.Right < width)
                    {
                        g.DrawLine(separator, rect.Right, y, width, y);
                    }
                }
                else
                {
                    g.DrawLine(separator, 0, y, width, y);
                }
            }
        }

        private void OnStripMouseMove(object sender, MouseEventArgs e)
        {
            var hoverIndex = HitTestTab(e.Location);
            if (hoverIndex != _hoverIndex)
            {
                _hoverIndex = hoverIndex;
                _strip.Invalidate();
            }

            _strip.Cursor = hoverIndex >= 0 ? Cursors.Hand : Cursors.Default;
        }

        private void OnStripMouseLeave(object sender, EventArgs e)
        {
            _hoverIndex = -1;
            _strip.Cursor = Cursors.Default;
            _strip.Invalidate();
        }

        private void OnStripMouseClick(object sender, MouseEventArgs e)
        {
            var index = HitTestTab(e.Location);
            if (index >= 0)
            {
                SelectedIndex = index;
            }
        }

        private int HitTestTab(Point location)
        {
            for (var i = 0; i < _tabHitAreas.Count; i++)
            {
                if (_tabHitAreas[i].Contains(location))
                {
                    return i;
                }
            }

            return -1;
        }

        private void SyncTabPageTheme()
        {
            var theme = _theme ?? ThemeManager.Colors;
            foreach (TabPage page in _inner.TabPages)
            {
                page.BackColor = theme.BackgroundPrimary;
                page.ForeColor = theme.TextPrimary;
            }

            _strip.Invalidate();
        }
    }
}
