using System.Diagnostics;
using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Threading;
using AxCopilot.Services;

namespace AxCopilot.Views;

/// <summary>
/// 화면 하단에 고정되는 미니 독 바.
/// 설정(DockBarItems)에 따라 표시 항목이 결정됩니다.
/// 가능한 항목: launcher, clipboard, capture, agent, clock, cpu, ram, quickinput
/// </summary>
public partial class DockBarWindow : Window
{
    private DispatcherTimer? _timer;
    private PerformanceCounter? _cpuCounter;
    private TextBlock? _cpuText;
    private TextBlock? _ramText;
    private TextBlock? _clockText;
    private TextBox? _quickInput;

    /// <summary>런처에 검색어를 전달하는 콜백.</summary>
    public Action<string>? OnQuickSearch { get; set; }

    /// <summary>캡처 직접 실행 콜백.</summary>
    public Action? OnCapture { get; set; }

    /// <summary>AX Agent 대화창 열기 콜백.</summary>
    public Action? OnOpenAgent { get; set; }

    // 표시 가능한 모든 아이템 정의
    private static readonly (string Key, string Icon, string Tooltip)[] AllItems =
    {
        ("launcher",   "\uE721", "AX Commander"),
        ("clipboard",  "\uE77F", "클립보드 히스토리"),
        ("capture",    "\uE722", "화면 캡처"),
        ("agent",      "\uE8BD", "AX Agent"),
        ("clock",      "\uE823", "시계"),
        ("cpu",        "\uE950", "CPU"),
        ("ram",        "\uE7F4", "RAM"),
        ("quickinput", "\uE8D3", "빠른 입력"),
    };

    private DispatcherTimer? _glowTimer;

    /// <summary>설정 저장 콜백 (위치 저장용).</summary>
    public Action<double, double>? OnPositionChanged { get; set; }

    public DockBarWindow()
    {
        InitializeComponent();

        MouseLeftButtonDown += (_, e) => { if (e.LeftButton == MouseButtonState.Pressed) try { DragMove(); } catch (Exception) { } };
        LocationChanged += (_, _) => OnPositionChanged?.Invoke(Left, Top);
        Loaded += (_, _) => PositionDock();
        Closed += (_, _) => { _timer?.Stop(); _glowTimer?.Stop(); _cpuCounter?.Dispose(); };
    }

    /// <summary>투명도, 위치, 글로우를 설정에서 적용합니다.</summary>
    public void ApplySettings(double opacity, double left, double top, bool rainbowGlow)
    {
        Opacity = Math.Clamp(opacity, 0.3, 1.0);

        if (left >= 0 && top >= 0)
        {
            Left = left;
            Top = top;
        }
        else
        {
            // -1이면 중앙으로 이동
            Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Loaded, PositionDock);
        }

        if (rainbowGlow)
            StartRainbowGlow();
        else
            StopRainbowGlow();
    }

    private void StartRainbowGlow()
    {
        RainbowGlowBorder.Visibility = Visibility.Visible;
        _glowTimer ??= new DispatcherTimer { Interval = TimeSpan.FromMilliseconds(50) };
        var startAngle = 0.0;
        _glowTimer.Tick += (_, _) =>
        {
            startAngle += 2;
            if (startAngle >= 360) startAngle -= 360;
            var rad = startAngle * Math.PI / 180.0;
            RainbowBrush.StartPoint = new Point(0.5 + 0.5 * Math.Cos(rad), 0.5 + 0.5 * Math.Sin(rad));
            RainbowBrush.EndPoint = new Point(0.5 - 0.5 * Math.Cos(rad), 0.5 - 0.5 * Math.Sin(rad));
        };
        _glowTimer.Start();
    }

    private void StopRainbowGlow()
    {
        _glowTimer?.Stop();
        RainbowGlowBorder.Visibility = Visibility.Collapsed;
    }

    // 기획된 고정 표시 순서
    private static readonly string[] FixedOrder =
        { "launcher", "clipboard", "capture", "agent", "clock", "cpu", "ram", "quickinput" };

    /// <summary>설정에서 표시 항목 목록을 받아 독 바를 빌드합니다. 표시 순서는 기획 순서 고정.</summary>
    public void BuildFromSettings(List<string> itemKeys)
    {
        DockContent.Children.Clear();
        _cpuText = null; _ramText = null; _clockText = null; _quickInput = null;

        var primaryText = TryFindResource("PrimaryText") as Brush ?? Brushes.White;
        var secondaryText = TryFindResource("SecondaryText") as Brush ?? Brushes.Gray;
        var accentBrush = TryFindResource("AccentColor") as Brush ?? Brushes.CornflowerBlue;
        bool needTimer = false;
        bool addedFirst = false;

        // 기획 순서에서 활성화된 항목만 순서대로 표시
        var enabledSet = new HashSet<string>(itemKeys, StringComparer.OrdinalIgnoreCase);
        foreach (var key in FixedOrder.Where(k => enabledSet.Contains(k)))
        {
            if (addedFirst) AddSeparator();
            addedFirst = true;

            switch (key)
            {
                case "launcher":
                    AddButton("\uE721", "AX Commander", primaryText, () => OnQuickSearch?.Invoke(""));
                    break;
                case "clipboard":
                    AddButton("\uE77F", "클립보드", primaryText, () => OnQuickSearch?.Invoke("#"));
                    break;
                case "capture":
                    AddButton("\uE722", "캡처", primaryText, () =>
                    {
                        if (OnCapture != null) OnCapture();
                        else OnQuickSearch?.Invoke("cap");
                    });
                    break;
                case "agent":
                    AddButton("\uE8BD", "AI", primaryText, () =>
                    {
                        if (OnOpenAgent != null) OnOpenAgent();
                        else OnQuickSearch?.Invoke("!");
                    });
                    break;
                case "clock":
                    _clockText = new TextBlock
                    {
                        Text = DateTime.Now.ToString("HH:mm"),
                        FontSize = 12, FontWeight = FontWeights.SemiBold,
                        Foreground = primaryText,
                        VerticalAlignment = VerticalAlignment.Center,
                        Margin = new Thickness(6, 0, 6, 0),
                    };
                    DockContent.Children.Add(_clockText);
                    needTimer = true;
                    break;
                case "cpu":
                    var cpuPanel = new StackPanel { Orientation = Orientation.Horizontal, VerticalAlignment = VerticalAlignment.Center };
                    cpuPanel.Children.Add(new TextBlock
                    {
                        Text = "\uE950", FontFamily = ThemeResourceHelper.SegoeMdl2,
                        FontSize = 11, Foreground = accentBrush,
                        VerticalAlignment = VerticalAlignment.Center, Margin = new Thickness(0, 0, 3, 0)
                    });
                    _cpuText = new TextBlock { Text = "0%", FontSize = 11, Foreground = secondaryText, VerticalAlignment = VerticalAlignment.Center, Width = 28, TextAlignment = TextAlignment.Right };
                    cpuPanel.Children.Add(_cpuText);
                    DockContent.Children.Add(cpuPanel);
                    needTimer = true;
                    if (_cpuCounter == null)
                        try { _cpuCounter = new PerformanceCounter("Processor", "% Processor Time", "_Total"); _cpuCounter.NextValue(); } catch (Exception) { }
                    break;
                case "ram":
                    var ramPanel = new StackPanel { Orientation = Orientation.Horizontal, VerticalAlignment = VerticalAlignment.Center };
                    ramPanel.Children.Add(new TextBlock
                    {
                        Text = "\uE7F4", FontFamily = ThemeResourceHelper.SegoeMdl2,
                        FontSize = 11, Foreground = accentBrush,
                        VerticalAlignment = VerticalAlignment.Center, Margin = new Thickness(0, 0, 3, 0)
                    });
                    _ramText = new TextBlock { Text = "0%", FontSize = 11, Foreground = secondaryText, VerticalAlignment = VerticalAlignment.Center, Width = 28, TextAlignment = TextAlignment.Right };
                    ramPanel.Children.Add(_ramText);
                    DockContent.Children.Add(ramPanel);
                    needTimer = true;
                    break;
                case "quickinput":
                    var inputBorder = new Border
                    {
                        Background = TryFindResource("ItemBackground") as Brush ?? Brushes.Transparent,
                        CornerRadius = new CornerRadius(8), Padding = new Thickness(8, 3, 8, 3),
                        VerticalAlignment = VerticalAlignment.Center,
                    };
                    var inputPanel = new StackPanel { Orientation = Orientation.Horizontal };
                    inputPanel.Children.Add(new TextBlock
                    {
                        Text = "\uE721", FontFamily = ThemeResourceHelper.SegoeMdl2,
                        FontSize = 11, Foreground = accentBrush,
                        VerticalAlignment = VerticalAlignment.Center, Margin = new Thickness(0, 0, 5, 0)
                    });
                    _quickInput = new TextBox
                    {
                        Width = 100, FontSize = 11,
                        Foreground = primaryText,
                        CaretBrush = accentBrush,
                        Background = Brushes.Transparent, BorderThickness = new Thickness(0),
                        VerticalAlignment = VerticalAlignment.Center,
                    };
                    _quickInput.KeyDown += QuickInput_KeyDown;
                    inputPanel.Children.Add(_quickInput);
                    inputBorder.Child = inputPanel;
                    DockContent.Children.Add(inputBorder);
                    break;
            }
        }

        if (needTimer)
        {
            _timer ??= new DispatcherTimer { Interval = TimeSpan.FromSeconds(1) };
            _timer.Tick -= OnTick;
            _timer.Tick += OnTick;
            _timer.Start();
            OnTick(null, EventArgs.Empty);
        }
    }

    /// <summary>사용 가능한 모든 아이템 키와 라벨 목록을 반환합니다.</summary>
    public static IReadOnlyList<(string Key, string Icon, string Tooltip)> AvailableItems => AllItems;

    private void AddButton(string icon, string tooltip, Brush foreground, Action click)
    {
        var border = new Border
        {
            Width = 30, Height = 30,
            CornerRadius = new CornerRadius(8),
            Background = new SolidColorBrush(Color.FromArgb(0x01, 0xFF, 0xFF, 0xFF)), // 거의 투명하지만 히트 테스트 가능
            Cursor = Cursors.Hand,
            ToolTip = tooltip,
            Margin = new Thickness(2, 0, 2, 0),
        };
        border.Child = new TextBlock
        {
            Text = icon,
            FontFamily = ThemeResourceHelper.SegoeMdl2,
            FontSize = 14, Foreground = foreground,
            HorizontalAlignment = HorizontalAlignment.Center,
            VerticalAlignment = VerticalAlignment.Center,
            IsHitTestVisible = false, // 텍스트가 이벤트를 가로채지 않도록
        };
        border.MouseEnter += (s, _) => { if (s is Border b) b.Background = new SolidColorBrush(Color.FromArgb(0x22, 0xFF, 0xFF, 0xFF)); };
        border.MouseLeave += (s, _) => { if (s is Border b) b.Background = new SolidColorBrush(Color.FromArgb(0x01, 0xFF, 0xFF, 0xFF)); };
        border.MouseLeftButtonDown += (_, e) => { e.Handled = true; click(); };
        DockContent.Children.Add(border);
    }

    private void AddSeparator()
    {
        DockContent.Children.Add(new Border
        {
            Width = 1, Height = 20, Margin = new Thickness(6, 0, 6, 0),
            Background = TryFindResource("SeparatorColor") as Brush ?? Brushes.Gray,
        });
    }

    private void PositionDock()
    {
        var screen = SystemParameters.WorkArea;
        Left = (screen.Width - ActualWidth) / 2 + screen.Left;
        Top = screen.Bottom - ActualHeight - 8;
    }

    private void OnTick(object? sender, EventArgs e)
    {
        if (_clockText != null)
            _clockText.Text = DateTime.Now.ToString("HH:mm");

        if (_cpuText != null)
        {
            try { _cpuText.Text = $"{_cpuCounter?.NextValue() ?? 0:F0}%"; }
            catch (Exception) { _cpuText.Text = "-"; }
        }

        if (_ramText != null)
        {
            try
            {
                var m = new MEMORYSTATUSEX { dwLength = (uint)Marshal.SizeOf<MEMORYSTATUSEX>() };
                _ramText.Text = GlobalMemoryStatusEx(ref m) ? $"{m.dwMemoryLoad}%" : "-";
            }
            catch (Exception) { _ramText.Text = "-"; }
        }
    }

    [DllImport("kernel32.dll")] private static extern bool GlobalMemoryStatusEx(ref MEMORYSTATUSEX lpBuffer);

    [StructLayout(LayoutKind.Sequential)]
    private struct MEMORYSTATUSEX
    {
        public uint dwLength; public uint dwMemoryLoad;
        public ulong ullTotalPhys, ullAvailPhys, ullTotalPageFile, ullAvailPageFile, ullTotalVirtual, ullAvailVirtual, ullAvailExtendedVirtual;
    }

    private void QuickInput_KeyDown(object sender, KeyEventArgs e)
    {
        if (e.Key == Key.Enter && _quickInput != null && !string.IsNullOrWhiteSpace(_quickInput.Text))
        {
            OnQuickSearch?.Invoke(_quickInput.Text);
            _quickInput.Text = "";
            e.Handled = true;
        }
        else if (e.Key == Key.Escape && _quickInput != null)
        {
            _quickInput.Text = "";
            e.Handled = true;
        }
    }

    private void Window_KeyDown(object sender, KeyEventArgs e)
    {
        if (e.Key == Key.Escape) Hide();
    }
}
