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;

namespace AxCopilot.Views;

public partial class ChatWindow
{
    // ─── 프롬프트 템플릿 팝업 ────────────────────────────────────────────

    private void BtnTemplateSelector_Click(object sender, RoutedEventArgs e)
    {
        var templates = Llm.PromptTemplates;
        TemplateItems.Items.Clear();

        if (templates == null || templates.Count == 0)
        {
            TemplateEmptyHint.Visibility = Visibility.Visible;
            TemplatePopup.IsOpen = true;
            return;
        }

        TemplateEmptyHint.Visibility = Visibility.Collapsed;

        foreach (var tpl in templates)
        {
            var item = new Border
            {
                Background = Brushes.Transparent,
                CornerRadius = new CornerRadius(8),
                Padding = new Thickness(10, 8, 10, 8),
                Margin = new Thickness(2),
                Cursor = System.Windows.Input.Cursors.Hand,
                Tag = tpl.Content,
            };

            var stack = new StackPanel();
            stack.Children.Add(new TextBlock
            {
                Text = tpl.Name,
                FontSize = 13,
                FontWeight = FontWeights.SemiBold,
                Foreground = (Brush)FindResource("PrimaryText"),
            });
            var preview = tpl.Content.Length > 60 ? tpl.Content[..60] + "…" : tpl.Content;
            stack.Children.Add(new TextBlock
            {
                Text = preview,
                FontSize = 11,
                Foreground = (Brush)FindResource("SecondaryText"),
                TextTrimming = TextTrimming.CharacterEllipsis,
                Margin = new Thickness(0, 2, 0, 0),
            });
            item.Child = stack;

            item.MouseEnter += (s, _) =>
            {
                if (s is Border b) b.Background = (Brush)FindResource("ItemBackground");
            };
            item.MouseLeave += (s, _) =>
            {
                if (s is Border b) b.Background = Brushes.Transparent;
            };
            item.MouseLeftButtonUp += (s, _) =>
            {
                if (s is Border b && b.Tag is string content)
                {
                    InputBox.Text = content;
                    InputBox.CaretIndex = InputBox.Text.Length;
                    InputBox.Focus();
                    TemplatePopup.IsOpen = false;
                }
            };

            TemplateItems.Items.Add(item);
        }

        TemplatePopup.IsOpen = true;
    }

    // ─── 모델 전환 ──────────────────────────────────────────────────────

    // Gemini/Claude 사전 정의 모델 목록
    private static readonly (string Id, string Label)[] GeminiModels =
    {
        ("gemini-2.5-pro",                  "Gemini 2.5 Pro"),
        ("gemini-2.5-flash",                "Gemini 2.5 Flash"),
        ("gemini-2.5-flash-lite",           "Gemini 2.5 Flash Lite"),
        ("gemini-2.0-flash",                "Gemini 2.0 Flash"),
        ("gemini-2.0-flash-lite",           "Gemini 2.0 Flash Lite"),
    };
    private static readonly (string Id, string Label)[] ClaudeModels =
    {
        ("claude-opus-4-6",              "Claude Opus 4.6"),
        ("claude-sonnet-4-6",            "Claude Sonnet 4.6"),
        ("claude-haiku-4-5-20251001",    "Claude Haiku 4.5"),
        ("claude-sonnet-4-5-20250929",   "Claude Sonnet 4.5"),
        ("claude-opus-4-20250514",       "Claude Opus 4"),
    };

    /// <summary>현재 선택된 모델의 표시명을 반환합니다.</summary>
    private string GetCurrentModelDisplayName()
    {
        var llm = Llm;
        var service = llm.Service.ToLowerInvariant();

        if (service is "ollama" or "vllm")
        {
            // 등록 모델에서 별칭 찾기
            var registered = llm.RegisteredModels
                .FirstOrDefault(rm => rm.EncryptedModelName == llm.Model);
            if (registered != null) return registered.Alias;
            return string.IsNullOrEmpty(llm.Model) ? "(미설정)" : "••••";
        }

        if (service == "gemini")
        {
            var m = GeminiModels.FirstOrDefault(g => g.Id == llm.Model);
            return m.Label ?? llm.Model;
        }
        if (service == "claude")
        {
            var m = ClaudeModels.FirstOrDefault(c => c.Id == llm.Model);
            return m.Label ?? llm.Model;
        }
        return string.IsNullOrEmpty(llm.Model) ? "(미설정)" : llm.Model;
    }

    private void UpdateModelLabel()
    {
        var service = Llm.Service.ToLowerInvariant();
        var serviceLabel = service switch
        {
            "gemini" => "Gemini",
            "claude" => "Claude",
            "vllm"   => "vLLM",
            _        => "Ollama",
        };
        var modelName = GetCurrentModelDisplayName();
        ModelLabel.Text = $"{serviceLabel} · {modelName}";
        // Phase 17-UI-C: SessionHeaderBar 모델 칩 동기화
        SessionHeaderBar?.SetModel($"{serviceLabel} · {modelName}");
    }

    private void BtnModelSelector_Click(object sender, RoutedEventArgs e)
    {
        var llm = Llm;

        // 팝업 열기 전 원본 서비스/모델 백업 — 모델 미선택 후 닫으면 롤백
        var originalService = llm.Service;
        var originalModel   = llm.Model;
        var modelConfirmed  = false;

        var borderBrush = ThemeResourceHelper.Border(this);
        var primaryText = ThemeResourceHelper.Primary(this);
        var secondaryText = ThemeResourceHelper.Secondary(this);
        var hoverBg = ThemeResourceHelper.HoverBg(this);
        var checkColor = new SolidColorBrush(Color.FromRgb(0x38, 0xA1, 0x69));
        var activeSvcBg = new SolidColorBrush(Color.FromArgb(0x18, 0x4B, 0x5E, 0xFC));

        var (popup, stack) = PopupMenuHelper.Create(BtnModelSelector, this, PlacementMode.Top, minWidth: 240, maxHeight: 460);

        // 모델 목록을 담을 패널 (서비스 변경 시 동적 재구성)
        var modelSection = new StackPanel();

        Border CreateMenuItem(string text, bool isChecked, Action onClick, bool closeOnClick = true)
        {
            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(1, GridUnitType.Star) });
            g.ColumnDefinitions.Add(new ColumnDefinition { Width = new GridLength(20) });

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

            if (isChecked)
            {
                var checkIcon = new Canvas { Width = 14, Height = 14, VerticalAlignment = VerticalAlignment.Center };
                checkIcon.Children.Add(new System.Windows.Shapes.Path
                {
                    Data = Geometry.Parse("M 2 7 L 5.5 10.5 L 12 4"),
                    Stroke = checkColor, StrokeThickness = 2,
                    StrokeStartLineCap = PenLineCap.Round, StrokeEndLineCap = PenLineCap.Round, StrokeLineJoin = PenLineJoin.Round,
                });
                Grid.SetColumn(checkIcon, 1);
                g.Children.Add(checkIcon);
            }

            item.Child = g;
            // 호버 시 배경색 + 살짝 확대
            item.RenderTransformOrigin = new Point(0.5, 0.5);
            item.RenderTransform = new ScaleTransform(1, 1);
            item.MouseEnter += (s, _) =>
            {
                if (s is Border b) b.Background = hoverBg;
                var st = item.RenderTransform as ScaleTransform;
                st?.BeginAnimation(ScaleTransform.ScaleXProperty, new DoubleAnimation(1.02, TimeSpan.FromMilliseconds(120)));
                st?.BeginAnimation(ScaleTransform.ScaleYProperty, new DoubleAnimation(1.02, TimeSpan.FromMilliseconds(120)));
            };
            item.MouseLeave += (s, _) =>
            {
                if (s is Border b) b.Background = Brushes.Transparent;
                var st = item.RenderTransform as ScaleTransform;
                st?.BeginAnimation(ScaleTransform.ScaleXProperty, new DoubleAnimation(1.0, TimeSpan.FromMilliseconds(150)));
                st?.BeginAnimation(ScaleTransform.ScaleYProperty, new DoubleAnimation(1.0, TimeSpan.FromMilliseconds(150)));
            };
            item.MouseLeftButtonUp += (_, _) =>
            {
                if (closeOnClick) popup.IsOpen = false;
                onClick();
            };
            return item;
        }

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

        // 모델 목록 빌드 함수 (서비스 변경 시 호출)
        void RebuildModelList(string service)
        {
            modelSection.Children.Clear();

            modelSection.Children.Add(new TextBlock
            {
                Text = "모델", FontSize = 11, Foreground = secondaryText,
                Margin = new Thickness(10, 4, 0, 4), FontWeight = FontWeights.SemiBold,
            });

            if (service is "ollama" or "vllm")
            {
                var registered = llm.RegisteredModels.Where(rm => rm.Service == service).ToList();
                if (registered.Count == 0)
                {
                    modelSection.Children.Add(new TextBlock
                    {
                        Text = "등록된 모델 없음 — 설정에서 추가",
                        FontSize = 11.5, Foreground = secondaryText, FontStyle = FontStyles.Italic,
                        Margin = new Thickness(10, 4, 10, 4),
                    });
                }
                else
                {
                    foreach (var rm in registered)
                    {
                        var capturedEnc = rm.EncryptedModelName;
                        modelSection.Children.Add(CreateMenuItem(rm.Alias, llm.Model == rm.EncryptedModelName, () =>
                        {
                            Llm.Model = capturedEnc;
                            _settings.Save();
                            modelConfirmed = true;
                            UpdateModelLabel();
                        }));
                    }
                }
            }
            else if (service == "gemini")
            {
                foreach (var (id, label) in GeminiModels)
                {
                    var capturedId = id;
                    modelSection.Children.Add(CreateMenuItem(label, llm.Model == id, () =>
                    {
                        Llm.Model = capturedId;
                        _settings.Save();
                        modelConfirmed = true;
                        UpdateModelLabel();
                    }));
                }
            }
            else if (service == "claude")
            {
                foreach (var (id, label) in ClaudeModels)
                {
                    var capturedId = id;
                    modelSection.Children.Add(CreateMenuItem(label, llm.Model == id, () =>
                    {
                        Llm.Model = capturedId;
                        _settings.Save();
                        modelConfirmed = true;
                        UpdateModelLabel();
                    }));
                }
            }
        }

        // 서비스 헤더
        stack.Children.Add(new TextBlock
        {
            Text = "서비스", FontSize = 11, Foreground = secondaryText,
            Margin = new Thickness(10, 4, 0, 4), FontWeight = FontWeights.SemiBold,
        });

        // 서비스 버튼들을 담을 패널 (체크마크 갱신용)
        var serviceItems = new StackPanel();
        var services = new[] { ("ollama", "Ollama"), ("vllm", "vLLM"), ("gemini", "Gemini"), ("claude", "Claude") };

        void BuildServiceItems()
        {
            serviceItems.Children.Clear();
            var currentSvc = llm.Service.ToLowerInvariant();
            foreach (var (svc, label) in services)
            {
                var capturedSvc = svc;
                serviceItems.Children.Add(CreateMenuItem(label, currentSvc == svc, () =>
                {
                    // 서비스만 임시 반영 — Save는 모델 선택 시에만 호출
                    Llm.Service = capturedSvc;
                    UpdateModelLabel();
                    // 서비스 변경 후 모델 목록 + 서비스 체크마크 갱신 (팝업은 열린 채로)
                    BuildServiceItems();
                    RebuildModelList(capturedSvc);
                }, closeOnClick: false));
            }
        }

        BuildServiceItems();
        stack.Children.Add(serviceItems);
        stack.Children.Add(CreateSeparator());

        // 모델 목록 초기 빌드
        RebuildModelList(llm.Service.ToLowerInvariant());
        stack.Children.Add(modelSection);

        // 팝업이 닫힐 때 모델 미선택이면 서비스/모델 원래대로 롤백
        popup.Closed += (_, _) =>
        {
            if (!modelConfirmed)
            {
                Llm.Service = originalService;
                Llm.Model   = originalModel;
                UpdateModelLabel();
            }
        };

        popup.IsOpen = true;
    }

    private void BtnNewChat_Click(object sender, RoutedEventArgs e)
    {
        StartNewConversation();
        InputBox.Focus();
    }

    public void ResumeConversation(string conversationId)
    {
        var conv = _storage.Load(conversationId);
        if (conv != null)
        {
            lock (_convLock) _currentConversation = conv;
            UpdateChatTitle();
            RefreshConversationList();
            RenderMessages();
            UpdateFolderBar();
        }
        InputBox.Focus();
    }

    public void StartNewAndFocus()
    {
        StartNewConversation();
        InputBox.Focus();
    }

    private void BtnDeleteAll_Click(object sender, RoutedEventArgs e)
    {
        var result = CustomMessageBox.Show(
            "저장된 모든 대화 내역을 삭제하시겠습니까?\n이 작업은 되돌릴 수 없습니다.",
            "대화 전체 삭제",
            MessageBoxButton.YesNo,
            MessageBoxImage.Warning);

        if (result != MessageBoxResult.Yes) return;

        _storage.DeleteAll();
        lock (_convLock) _currentConversation = null;
        MessagePanel.Children.Clear();
        EmptyState.Visibility = Visibility.Visible;
        UpdateChatTitle();
        RefreshConversationList();
    }
}
