using System.Windows;
using System.Windows.Controls;
using System.Windows.Controls.Primitives;
using System.Windows.Input;
using System.Windows.Media;
using System.Windows.Media.Animation;
using System.Windows.Threading;
using AxCopilot.Models;
using AxCopilot.Services;

namespace AxCopilot.Views;

public partial class ChatWindow
{
    // ─── 사용자 정보 ────────────────────────────────────────────────────

    private void SetupUserInfo()
    {
        var userName = Environment.UserName;
        // AD\, AD/, AD: 접두사 제거
        var cleanName = userName;
        foreach (var sep in new[] { '\\', '/', ':' })
        {
            var idx = cleanName.LastIndexOf(sep);
            if (idx >= 0) cleanName = cleanName[(idx + 1)..];
        }

        var initial = cleanName.Length > 0 ? cleanName[..1].ToUpper() : "U";
        var pcName = Environment.MachineName;

        UserInitialSidebar.Text = initial;
        UserInitialIconBar.Text = initial;
        UserNameText.Text = cleanName;
        UserPcText.Text = pcName;
        BtnUserIconBar.ToolTip = $"{cleanName} ({pcName})";
    }

    // ─── 스크롤 동작 ──────────────────────────────────────────────────

    private void MessageScroll_ScrollChanged(object sender, ScrollChangedEventArgs e)
    {
        // 스크롤 가능 영역이 없으면(콘텐츠가 짧음) 항상 바닥
        if (MessageScroll.ScrollableHeight <= 1)
        {
            _userScrolled = false;
            return;
        }

        // 콘텐츠 크기 변경(ExtentHeightChange > 0)에 의한 스크롤은 무시 — 사용자 조작만 감지
        if (Math.Abs(e.ExtentHeightChange) > 0.5)
            return;

        var atBottom = MessageScroll.VerticalOffset >= MessageScroll.ScrollableHeight - 40;
        _userScrolled = !atBottom;
    }

    private void AutoScrollIfNeeded()
    {
        if (!_userScrolled)
            SmoothScrollToEnd();
    }

    /// <summary>새 응답 시작 시 강제로 하단 스크롤합니다 (사용자 스크롤 상태 리셋).</summary>
    private void ForceScrollToEnd()
    {
        _userScrolled = false;
        Dispatcher.InvokeAsync(() => SmoothScrollToEnd(), DispatcherPriority.Background);
    }

    /// <summary>부드러운 자동 스크롤 — 하단으로 부드럽게 이동합니다.</summary>
    private void SmoothScrollToEnd()
    {
        var targetOffset = MessageScroll.ScrollableHeight;
        var currentOffset = MessageScroll.VerticalOffset;
        var diff = targetOffset - currentOffset;

        // 차이가 작으면 즉시 이동 (깜빡임 방지)
        if (diff <= 60)
        {
            MessageScroll.ScrollToEnd();
            return;
        }

        // 부드럽게 스크롤 (DoubleAnimation)
        var animation = new DoubleAnimation
        {
            From = currentOffset,
            To = targetOffset,
            Duration = TimeSpan.FromMilliseconds(200),
            EasingFunction = new CubicEase { EasingMode = EasingMode.EaseOut },
        };
        animation.Completed += (_, _) => MessageScroll.ScrollToVerticalOffset(targetOffset);

        // ScrollViewer에 직접 애니메이션을 적용할 수 없으므로 타이머 기반으로 보간
        var startTime = DateTime.UtcNow;
        var timer = new DispatcherTimer { Interval = TimeSpan.FromMilliseconds(16) }; // ~60fps
        EventHandler tickHandler = null!;
        tickHandler = (_, _) =>
        {
            var elapsed = (DateTime.UtcNow - startTime).TotalMilliseconds;
            var progress = Math.Min(elapsed / 200.0, 1.0);
            var eased = 1.0 - Math.Pow(1.0 - progress, 3);
            var offset = currentOffset + diff * eased;
            MessageScroll.ScrollToVerticalOffset(offset);

            if (progress >= 1.0)
            {
                timer.Stop();
                timer.Tick -= tickHandler;
            }
        };
        timer.Tick += tickHandler;
        timer.Start();
    }

    // ─── 대화 제목 인라인 편집 ──────────────────────────────────────────

    private void ChatTitle_MouseDown(object sender, MouseButtonEventArgs e)
    {
        lock (_convLock)
        {
            if (_currentConversation == null) return;
        }
        ChatTitle.Visibility = Visibility.Collapsed;
        ChatTitleEdit.Text = ChatTitle.Text;
        ChatTitleEdit.Visibility = Visibility.Visible;
        ChatTitleEdit.Focus();
        ChatTitleEdit.SelectAll();
    }

    private void ChatTitleEdit_LostFocus(object sender, RoutedEventArgs e) => CommitTitleEdit();
    private void ChatTitleEdit_KeyDown(object sender, KeyEventArgs e)
    {
        if (e.Key == Key.Enter) { CommitTitleEdit(); e.Handled = true; }
        if (e.Key == Key.Escape) { CancelTitleEdit(); e.Handled = true; }
    }

    private void CommitTitleEdit()
    {
        var newTitle = ChatTitleEdit.Text.Trim();
        ChatTitleEdit.Visibility = Visibility.Collapsed;
        ChatTitle.Visibility = Visibility.Visible;

        if (string.IsNullOrEmpty(newTitle)) return;

        lock (_convLock)
        {
            if (_currentConversation == null) return;
            _currentConversation.Title = newTitle;
        }

        ChatTitle.Text = newTitle;
        try
        {
            ChatConversation conv;
            lock (_convLock) conv = _currentConversation!;
            _storage.Save(conv);
        }
        catch (Exception) { /* 대화 저장 실패 — UI 차단 방지 */ }
        RefreshConversationList();
    }

    private void CancelTitleEdit()
    {
        ChatTitleEdit.Visibility = Visibility.Collapsed;
        ChatTitle.Visibility = Visibility.Visible;
    }

    // ─── 카테고리 드롭다운 ──────────────────────────────────────────────

    private void BtnCategoryDrop_Click(object sender, RoutedEventArgs e)
    {
        var borderBrush = ThemeResourceHelper.Border(this);
        var primaryText = ThemeResourceHelper.Primary(this);
        var secondaryText = ThemeResourceHelper.Secondary(this);
        var hoverBg = ThemeResourceHelper.HoverBg(this);
        var accentBrush = ThemeResourceHelper.Accent(this);

        var (popup, stack) = PopupMenuHelper.Create(BtnCategoryDrop, this, PlacementMode.Bottom, minWidth: 180);
        popup.VerticalOffset = 4;

        Border CreateCatItem(string icon, string text, Brush iconColor, bool isSelected, Action onClick)
        {
            var item = new Border
            {
                Background = Brushes.Transparent,
                CornerRadius = new CornerRadius(8),
                Padding = new Thickness(10, 7, 10, 7),
                Margin = new Thickness(0, 1, 0, 1),
                Cursor = Cursors.Hand,
            };
            var g = new Grid();
            g.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(24) });
            g.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(1, GridUnitType.Star) });
            g.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(20) });

            var iconTb = new TextBlock
            {
                Text = icon, FontFamily = ThemeResourceHelper.SegoeMdl2,
                FontSize = 12, Foreground = iconColor, VerticalAlignment = VerticalAlignment.Center,
            };
            Grid.SetColumn(iconTb, 0);
            g.Children.Add(iconTb);

            var textTb = new TextBlock
            {
                Text = text, FontSize = 12.5, Foreground = primaryText,
                VerticalAlignment = VerticalAlignment.Center,
            };
            Grid.SetColumn(textTb, 1);
            g.Children.Add(textTb);

            if (isSelected)
            {
                var check = CreateSimpleCheck(accentBrush, 14);
                Grid.SetColumn(check, 2);
                g.Children.Add(check);
            }

            item.Child = g;
            item.MouseEnter += (s, _) => { if (s is Border b) b.Background = hoverBg; };
            item.MouseLeave += (s, _) => { if (s is Border b) b.Background = Brushes.Transparent; };
            item.MouseLeftButtonUp += (_, _) => { popup.IsOpen = false; onClick(); };
            return item;
        }

        Border CreateSep() => new()
        {
            Height = 1, Background = borderBrush, Opacity = 0.3, Margin = new Thickness(8, 4, 8, 4),
        };

        // 전체 보기
        var allLabel = _activeTab switch
        {
            "Cowork" => "모든 작업",
            "Code" => "모든 작업",
            _ => "모든 주제",
        };
        stack.Children.Add(CreateCatItem("\uE8BD", allLabel, secondaryText,
            string.IsNullOrEmpty(_selectedCategory),
            () => { _selectedCategory = ""; UpdateCategoryLabel(); RefreshConversationList(); }));

        stack.Children.Add(CreateSep());

        if (_activeTab == "Cowork" || _activeTab == "Code")
        {
            // 코워크/코드: 프리셋 카테고리 기반 필터
            var presets = Services.PresetService.GetByTabWithCustom(_activeTab, Llm.CustomPresets);
            var seen = new HashSet<string>();
            foreach (var p in presets)
            {
                if (p.IsCustom) continue; // 커스텀은 별도 그룹
                if (!seen.Add(p.Category)) continue;
                var capturedCat = p.Category;
                stack.Children.Add(CreateCatItem(p.Symbol, p.Label, BrushFromHex(p.Color),
                    _selectedCategory == capturedCat,
                    () => { _selectedCategory = capturedCat; UpdateCategoryLabel(); RefreshConversationList(); }));
            }
            // 커스텀 프리셋 통합 필터
            if (presets.Any(p => p.IsCustom))
            {
                stack.Children.Add(CreateSep());
                stack.Children.Add(CreateCatItem("\uE710", "커스텀 프리셋", secondaryText,
                    _selectedCategory == "__custom__",
                    () => { _selectedCategory = "__custom__"; UpdateCategoryLabel(); RefreshConversationList(); }));
            }
        }
        else
        {
            // Chat: 기존 ChatCategory 기반
            foreach (var (key, label, symbol, color) in ChatCategory.All)
            {
                var capturedKey = key;
                stack.Children.Add(CreateCatItem(symbol, label, BrushFromHex(color),
                    _selectedCategory == capturedKey,
                    () => { _selectedCategory = capturedKey; UpdateCategoryLabel(); RefreshConversationList(); }));
            }
            // 커스텀 프리셋 통합 필터 (Chat)
            var chatCustom = Llm.CustomPresets.Where(c => c.Tab == "Chat").ToList();
            if (chatCustom.Count > 0)
            {
                stack.Children.Add(CreateSep());
                stack.Children.Add(CreateCatItem("\uE710", "커스텀 프리셋", secondaryText,
                    _selectedCategory == "__custom__",
                    () => { _selectedCategory = "__custom__"; UpdateCategoryLabel(); RefreshConversationList(); }));
            }
        }

        popup.IsOpen = true;
    }

    private void UpdateCategoryLabel()
    {
        if (string.IsNullOrEmpty(_selectedCategory))
        {
            CategoryLabel.Text = _activeTab switch { "Cowork" or "Code" => "모든 작업", _ => "모든 주제" };
            CategoryIcon.Text = "\uE8BD";
        }
        else if (_selectedCategory == "__custom__")
        {
            CategoryLabel.Text = "커스텀 프리셋";
            CategoryIcon.Text = "\uE710";
        }
        else
        {
            // ChatCategory에서 찾기
            foreach (var (key, label, symbol, _) in ChatCategory.All)
            {
                if (key == _selectedCategory)
                {
                    CategoryLabel.Text = label;
                    CategoryIcon.Text = symbol;
                    return;
                }
            }
            // 프리셋 카테고리에서 찾기 (Cowork/Code)
            var presets = Services.PresetService.GetByTabWithCustom(_activeTab, Llm.CustomPresets);
            var match = presets.FirstOrDefault(p => p.Category == _selectedCategory);
            if (match != null)
            {
                CategoryLabel.Text = match.Label;
                CategoryIcon.Text = match.Symbol;
            }
            else
            {
                CategoryLabel.Text = _selectedCategory;
                CategoryIcon.Text = "\uE8BD";
            }
        }
    }

    // ─── 창 컨트롤 ──────────────────────────────────────────────────────

    // WindowChrome의 CaptionHeight가 드래그를 처리하므로 별도 핸들러 불필요

    protected override void OnSourceInitialized(EventArgs e)
    {
        base.OnSourceInitialized(e);
        var source = System.Windows.Interop.HwndSource.FromHwnd(
            new System.Windows.Interop.WindowInteropHelper(this).Handle);
        source?.AddHook(WndProc);
    }

    private IntPtr WndProc(IntPtr hwnd, int msg, IntPtr wParam, IntPtr lParam, ref bool handled)
    {
        // WM_GETMINMAXINFO — 최대화 시 작업 표시줄 영역 확보
        if (msg == 0x0024)
        {
            var screen = System.Windows.Forms.Screen.FromHandle(hwnd);
            var workArea = screen.WorkingArea;
            var monitor = screen.Bounds;

            var source = System.Windows.Interop.HwndSource.FromHwnd(hwnd);

            // MINMAXINFO: ptReserved(0,4) ptMaxSize(8,12) ptMaxPosition(16,20) ptMinTrackSize(24,28) ptMaxTrackSize(32,36)
            System.Runtime.InteropServices.Marshal.WriteInt32(lParam, 8, workArea.Width);   // ptMaxSize.cx
            System.Runtime.InteropServices.Marshal.WriteInt32(lParam, 12, workArea.Height); // ptMaxSize.cy
            System.Runtime.InteropServices.Marshal.WriteInt32(lParam, 16, workArea.Left - monitor.Left); // ptMaxPosition.x
            System.Runtime.InteropServices.Marshal.WriteInt32(lParam, 20, workArea.Top - monitor.Top);   // ptMaxPosition.y
            handled = true;
        }
        return IntPtr.Zero;
    }

    private void BtnMinimize_Click(object sender, RoutedEventArgs e) => WindowState = WindowState.Minimized;
    private void BtnMaximize_Click(object sender, RoutedEventArgs e)
    {
        WindowState = WindowState == WindowState.Maximized ? WindowState.Normal : WindowState.Maximized;
        MaximizeIcon.Text = WindowState == WindowState.Maximized ? "\uE923" : "\uE739"; // 복원/최대화 아이콘
    }
    private void BtnClose_Click(object sender, RoutedEventArgs e) => Close();
}
