using System.Windows;
using System.Windows.Controls;
using System.Windows.Input;
using System.Windows.Threading;
using AxCopilot.Models;
using AxCopilot.Services;

namespace AxCopilot.Views;

public partial class ChatWindow
{
    // ─── 전송 ──────────────────────────────────────────────────────────────

    public void SendInitialMessage(string message)
    {
        StartNewConversation();
        InputBox.Text = message;
        _ = SendMessageAsync();
    }

    private void StartNewConversation()
    {
        // 현재 대화가 있으면 저장 후 새 대화 시작
        lock (_convLock)
        {
            if (_currentConversation != null && _currentConversation.Messages.Count > 0)
                try { _storage.Save(_currentConversation); } catch (Exception) { /* 대화 저장 실패 — UI 차단 방지 */ }
            _currentConversation = new ChatConversation { Tab = _activeTab };
            // 작업 폴더가 설정에 있으면 새 대화에 자동 연결 (Cowork/Code 탭)
            var workFolder = Llm.WorkFolder;
            if (!string.IsNullOrEmpty(workFolder) && _activeTab != "Chat")
                _currentConversation.WorkFolder = workFolder;
        }
        // 탭 기억 초기화 (새 대화이므로)
        _tabConversationId[_activeTab] = null;
        MessagePanel.Children.Clear();
        EmptyState.Visibility = Visibility.Visible;
        _attachedFiles.Clear();
        RefreshAttachedFilesUI();
        UpdateChatTitle();
        RefreshConversationList();
        UpdateFolderBar();
        if (_activeTab == "Cowork") BuildBottomBar();
    }

    /// <summary>설정에 저장된 탭별 마지막 대화 ID를 복원하고, 현재 탭의 대화를 로드합니다.</summary>
    private void RestoreLastConversations()
    {
        var saved = Llm.LastConversationIds;
        if (saved == null || saved.Count == 0) return;

        foreach (var kv in saved)
        {
            if (_tabConversationId.ContainsKey(kv.Key) && !string.IsNullOrEmpty(kv.Value))
                _tabConversationId[kv.Key] = kv.Value;
        }

        // 현재 활성 탭의 대화를 즉시 로드
        var currentTabId = _tabConversationId.GetValueOrDefault(_activeTab);
        if (!string.IsNullOrEmpty(currentTabId))
        {
            var conv = _storage.Load(currentTabId);
            if (conv != null)
            {
                if (string.IsNullOrEmpty(conv.Tab)) conv.Tab = _activeTab;
                lock (_convLock) _currentConversation = conv;
                MessagePanel.Children.Clear();
                foreach (var msg in conv.Messages)
                    AddMessageBubble(msg.Role, msg.Content, animate: false, message: msg);
                EmptyState.Visibility = conv.Messages.Count > 0 ? Visibility.Collapsed : Visibility.Visible;
                UpdateChatTitle();
                UpdateFolderBar();
                LoadConversationSettings();
            }
        }
    }

    /// <summary>현재 _tabConversationId를 설정에 저장합니다.</summary>
    private void SaveLastConversations()
    {
        var dict = new Dictionary<string, string>();
        foreach (var kv in _tabConversationId)
        {
            if (!string.IsNullOrEmpty(kv.Value))
                dict[kv.Key] = kv.Value;
        }
        Llm.LastConversationIds = dict;
        try { _settings.Save(); } catch (Exception) { /* 설정 저장 실패 */ }
    }

    private async void BtnSend_Click(object sender, RoutedEventArgs e) => await SendMessageAsync();

    private async void InputBox_PreviewKeyDown(object sender, KeyEventArgs e)
    {
        // Ctrl+V: 클립보드 이미지 붙여넣기
        if (e.Key == Key.V && Keyboard.Modifiers.HasFlag(ModifierKeys.Control))
        {
            if (TryPasteClipboardImage())
            {
                e.Handled = true;
                return;
            }
            // 이미지가 아니면 기본 텍스트 붙여넣기로 위임
        }

        if (e.Key == Key.Enter)
        {
            if (Keyboard.Modifiers.HasFlag(ModifierKeys.Shift))
            {
                // Shift+Enter → 줄바꿈 (AcceptsReturn=true이므로 기본 동작으로 위임)
                return;
            }

            // 슬래시 팝업이 열려 있으면 선택된 항목 실행
            if (SlashPopup.IsOpen && _slashSelectedIndex >= 0)
            {
                e.Handled = true;
                ExecuteSlashSelectedItem();
                return;
            }

            // /help 직접 입력 시 도움말 창 표시
            if (InputBox.Text.Trim().Equals("/help", StringComparison.OrdinalIgnoreCase))
            {
                e.Handled = true;
                InputBox.Text = "";
                SlashPopup.IsOpen = false;
                ShowSlashHelpWindow();
                return;
            }

            // Enter만 → 메시지 전송
            e.Handled = true;
            await SendMessageAsync();
        }
    }

    /// <summary>클립보드에 이미지가 있으면 붙여넣기. 성공 시 true.</summary>
    private bool TryPasteClipboardImage()
    {
        if (!Llm.EnableImageInput) return false;
        if (!Clipboard.ContainsImage()) return false;

        try
        {
            var img = Clipboard.GetImage();
            if (img == null) return false;

            // base64 인코딩
            var encoder = new System.Windows.Media.Imaging.PngBitmapEncoder();
            encoder.Frames.Add(System.Windows.Media.Imaging.BitmapFrame.Create(img));
            using var ms = new System.IO.MemoryStream();
            encoder.Save(ms);
            var bytes = ms.ToArray();

            // 크기 제한 확인
            var maxKb = Llm.MaxImageSizeKb;
            if (maxKb <= 0) maxKb = 5120;
            if (bytes.Length > maxKb * 1024)
            {
                CustomMessageBox.Show($"이미지가 너무 큽니다 ({bytes.Length / 1024}KB, 최대 {maxKb}KB).",
                    "이미지 크기 초과", MessageBoxButton.OK, MessageBoxImage.Warning);
                return true; // 처리됨 (에러이지만 이미지였음)
            }

            var base64 = Convert.ToBase64String(bytes);
            var attachment = new ImageAttachment
            {
                Base64 = base64,
                MimeType = "image/png",
                FileName = $"clipboard_{DateTime.Now:HHmmss}.png",
            };

            _pendingImages.Add(attachment);
            AddImagePreview(attachment, img);
            return true;
        }
        catch (Exception ex)
        {
            Services.LogService.Debug($"클립보드 이미지 붙여넣기 실패: {ex.Message}");
            return false;
        }
    }

    /// <summary>이미지 미리보기 UI 추가.</summary>
    private void AddImagePreview(ImageAttachment attachment, System.Windows.Media.Imaging.BitmapSource? thumbnail = null)
    {
        var secondaryBrush = ThemeResourceHelper.Secondary(this);
        var hintBg = ThemeResourceHelper.Hint(this);

        var chip = new Border
        {
            Background = hintBg,
            CornerRadius = new CornerRadius(6),
            Padding = new Thickness(4),
            Margin = new Thickness(0, 0, 4, 4),
        };

        var sp = new StackPanel { Orientation = Orientation.Horizontal };

        // 썸네일 이미지
        if (thumbnail != null)
        {
            sp.Children.Add(new System.Windows.Controls.Image
            {
                Source = thumbnail,
                MaxHeight = 48, MaxWidth = 64,
                Stretch = System.Windows.Media.Stretch.Uniform,
                Margin = new Thickness(0, 0, 4, 0),
            });
        }
        else
        {
            // base64에서 썸네일 생성
            sp.Children.Add(new TextBlock
            {
                Text = "\uE8B9", FontFamily = ThemeResourceHelper.SegoeMdl2, FontSize = 16,
                Foreground = secondaryBrush, VerticalAlignment = VerticalAlignment.Center,
                Margin = new Thickness(2, 0, 4, 0),
            });
        }

        sp.Children.Add(new TextBlock
        {
            Text = attachment.FileName, FontSize = 10, Foreground = secondaryBrush,
            VerticalAlignment = VerticalAlignment.Center, MaxWidth = 100,
            TextTrimming = TextTrimming.CharacterEllipsis,
        });

        var capturedAttachment = attachment;
        var capturedChip = chip;
        var removeBtn = new Button
        {
            Content = new TextBlock { Text = "\uE711", FontFamily = ThemeResourceHelper.SegoeMdl2, FontSize = 8, Foreground = secondaryBrush },
            Background = System.Windows.Media.Brushes.Transparent, BorderThickness = new Thickness(0),
            Cursor = System.Windows.Input.Cursors.Hand, Padding = new Thickness(4, 2, 4, 2), Margin = new Thickness(2, 0, 0, 0),
        };
        removeBtn.Click += (_, _) =>
        {
            _pendingImages.Remove(capturedAttachment);
            AttachedFilesPanel.Items.Remove(capturedChip);
            if (_pendingImages.Count == 0 && _attachedFiles.Count == 0)
                AttachedFilesPanel.Visibility = Visibility.Collapsed;
        };
        sp.Children.Add(removeBtn);
        chip.Child = sp;

        AttachedFilesPanel.Items.Add(chip);
        AttachedFilesPanel.Visibility = Visibility.Visible;
    }

    private async Task SendMessageAsync()
    {
        var rawText = InputBox.Text.Trim();

        // 슬래시 칩이 활성화된 경우 명령어 앞에 붙임
        var text = _activeSlashCmd != null
            ? (_activeSlashCmd + " " + rawText).Trim()
            : rawText;
        HideSlashChip(restoreText: false);

        if (string.IsNullOrEmpty(text) || _isStreaming) return;

        // placeholder 정리
        ClearPromptCardPlaceholder();

        // Phase 18: SlashCommandRegistry 명령 우선 실행 (/compact, /memory, /plan 등)
        if (text.StartsWith("/"))
        {
            using var regCts = new CancellationTokenSource();
            if (await TryExecuteRegistrySlashCommandAsync(text, regCts.Token))
                return; // registry 명령이 처리됨 (내장 SlashCommands dict는 폴백)
        }

        // 슬래시 명령어 처리
        var (slashSystem, displayText) = ParseSlashCommand(text);

        // 탭 전환 시에도 올바른 탭에 저장하기 위해 시작 시점의 탭을 캡처
        var originTab = _activeTab;

        ChatConversation conv;
        lock (_convLock)
        {
            if (_currentConversation == null) _currentConversation = new ChatConversation { Tab = _activeTab };
            conv = _currentConversation;
        }

        var userMsg = new ChatMessage { Role = "user", Content = text };
        lock (_convLock) conv.Messages.Add(userMsg);

        if (conv.Messages.Count(m => m.Role == "user") == 1)
            conv.Title = text.Length > 30 ? text[..30] + "…" : text;

        UpdateChatTitle();
        AddMessageBubble("user", text);
        InputBox.Text = "";
        EmptyState.Visibility = Visibility.Collapsed;

        // 대화 통계 기록
        Services.UsageStatisticsService.RecordChat(_activeTab);

        ForceScrollToEnd(); // 사용자 메시지 전송 시 강제 하단 이동
        PlayRainbowGlow(); // 무지개 글로우 애니메이션

        _isStreaming = true;
        BtnSend.IsEnabled = false;
        BtnSend.Visibility = Visibility.Collapsed;
        BtnStop.Visibility = Visibility.Visible;
        if (_activeTab == "Cowork" || _activeTab == "Code")
            BtnPause.Visibility = Visibility.Visible;
        _streamCts = new CancellationTokenSource();

        var assistantMsg = new ChatMessage { Role = "assistant", Content = "" };
        lock (_convLock) conv.Messages.Add(assistantMsg);

        // 어시스턴트 스트리밍 컨테이너
        var streamContainer = CreateStreamingContainer(out var streamText);
        MessagePanel.Children.Add(streamContainer);
        ForceScrollToEnd(); // 응답 시작 시 강제 하단 이동

        var sb = new System.Text.StringBuilder();
        _activeStreamText    = streamText;
        _cachedStreamContent = "";
        _displayedLength     = 0;
        _cursorVisible       = true;
        _aiIconPulseStopped  = false;
        _cursorTimer.Start();
        _typingTimer.Start();
        _streamStartTime = DateTime.UtcNow;
        _elapsedTimer.Start();
        SetStatus("응답 생성 중...", spinning: true);

        // ── 자동 모델 라우팅 (try 외부 선언 — finally에서 정리) ──
        ModelRouteResult? routeResult = null;

        try
        {
            List<ChatMessage> sendMessages;
            lock (_convLock) sendMessages = conv.Messages.SkipLast(1).ToList();

            // 시스템 명령어가 있으면 삽입
            if (!string.IsNullOrEmpty(conv.SystemCommand))
                sendMessages.Insert(0, new ChatMessage { Role = "system", Content = conv.SystemCommand });

            // 슬래시 명령어 시스템 프롬프트 삽입
            if (!string.IsNullOrEmpty(slashSystem))
                sendMessages.Insert(0, new ChatMessage { Role = "system", Content = slashSystem });

            // 첨부 파일 컨텍스트 삽입
            if (_attachedFiles.Count > 0)
            {
                var fileContext = BuildFileContextPrompt();
                if (!string.IsNullOrEmpty(fileContext))
                {
                    var lastUserIdx = sendMessages.FindLastIndex(m => m.Role == "user");
                    if (lastUserIdx >= 0)
                        sendMessages[lastUserIdx] = new ChatMessage { Role = "user", Content = sendMessages[lastUserIdx].Content + fileContext };
                }
                // 첨부 파일 목록 기록 후 항상 정리 (파일 읽기 실패해도)
                userMsg.AttachedFiles = _attachedFiles.ToList();
                _attachedFiles.Clear();
                RefreshAttachedFilesUI();
            }

            // ── 이미지 첨부 ──
            if (_pendingImages.Count > 0)
            {
                userMsg.Images = _pendingImages.ToList();
                // 마지막 사용자 메시지에 이미지 데이터 연결
                var lastUserIdx = sendMessages.FindLastIndex(m => m.Role == "user");
                if (lastUserIdx >= 0)
                    sendMessages[lastUserIdx] = new ChatMessage
                    {
                        Role = "user",
                        Content = sendMessages[lastUserIdx].Content,
                        Images = _pendingImages.ToList(),
                    };
                _pendingImages.Clear();
                AttachedFilesPanel.Items.Clear();
                if (_attachedFiles.Count == 0) AttachedFilesPanel.Visibility = Visibility.Collapsed;
            }

            // ── 자동 모델 라우팅 ──
            if (Llm.EnableAutoRouter)
            {
                routeResult = _router.Route(text);
                if (routeResult != null)
                {
                    _llm.PushRouteOverride(routeResult.Service, routeResult.Model);
                    SetStatus($"라우팅: {routeResult.DetectedIntent} → {routeResult.DisplayName}", spinning: true);
                }
            }

            if (_activeTab is "Cowork" or "Code")
            {
                // Phase 34: Cowork/Code 공통 에이전트 루프 실행
                var agentResponse = await RunAgentLoopAsync(_activeTab, sendMessages, _streamCts!.Token);
                sb.Append(agentResponse);
                assistantMsg.Content = agentResponse;
                StopAiIconPulse();
                _cachedStreamContent = agentResponse;
            }
            else if (Llm.Streaming)
            {
                await foreach (var chunk in _llm.StreamAsync(sendMessages, _streamCts.Token))
                {
                    sb.Append(chunk);
                    StopAiIconPulse();
                    _cachedStreamContent = sb.ToString();
                    // UI 스레드에 제어 양보 — DispatcherTimer가 화면 갱신할 수 있도록
                    await Dispatcher.InvokeAsync(() => { }, DispatcherPriority.Background);
                }
                _cachedStreamContent = sb.ToString();
                assistantMsg.Content = _cachedStreamContent;

                // 타이핑 애니메이션이 남은 버퍼를 소진할 때까지 대기 (최대 600ms)
                var drainStart = DateTime.UtcNow;
                while (_displayedLength < _cachedStreamContent.Length
                       && (DateTime.UtcNow - drainStart).TotalMilliseconds < 600)
                {
                    await Dispatcher.InvokeAsync(() => { }, DispatcherPriority.Background);
                }
            }
            else
            {
                var response = await _llm.SendAsync(sendMessages, _streamCts.Token);
                sb.Append(response);
                assistantMsg.Content = response;
            }
        }
        catch (OperationCanceledException)
        {
            if (sb.Length == 0) sb.Append("(취소됨)");
            assistantMsg.Content = sb.ToString();
        }
        catch (Exception ex)
        {
            var errMsg = $"⚠ 오류: {ex.Message}";
            sb.Clear(); sb.Append(errMsg);
            assistantMsg.Content = errMsg;
            AddRetryButton();
        }
        finally
        {
            // 자동 라우팅 오버라이드 해제
            if (routeResult != null)
            {
                _llm.ClearRouteOverride();
                UpdateModelLabel();
            }

            _cursorTimer.Stop();
            _elapsedTimer.Stop();
            _typingTimer.Stop();
            HideStickyProgress();            // 에이전트 프로그레스 바 + 타이머 정리
            StopRainbowGlow();               // 레인보우 글로우 종료
            _activeStreamText    = null;
            _elapsedLabel        = null;
            _cachedStreamContent = "";
            _isStreaming          = false;
            BtnSend.IsEnabled     = true;
            BtnStop.Visibility    = Visibility.Collapsed;
            BtnSend.Visibility    = Visibility.Visible;
            _streamCts?.Dispose();
            _streamCts = null;
            SetStatusIdle();
        }

        // 스트리밍 plaintext → 마크다운 렌더링으로 교체
        FinalizeStreamingContainer(streamContainer, streamText, assistantMsg.Content, assistantMsg);
        AutoScrollIfNeeded();

        try { _storage.Save(conv); } catch (Exception ex) { Services.LogService.Debug($"대화 저장 실패: {ex.Message}"); }
        _tabConversationId[originTab] = conv.Id;
        RefreshConversationList();
    }
}
