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;
using AxCopilot.Services.Agent;

namespace AxCopilot.Views;

/// <summary>AX Agent 창. Claude Desktop 스타일 — 사이드바 + 카테고리 분류 + 타임라인.</summary>
public partial class ChatWindow : Window
{
    private readonly SettingsService _settings;
    /// <summary>LLM 설정 바로가기 — <c>_settings.Settings.Llm</c> 체인 액세스 단축.</summary>
    private LlmSettings Llm => _settings.Settings.Llm;
    /// <summary>App 인스턴스 바로가기 — <c>Application.Current as App</c> 반복 호출 제거.</summary>
    private static App? CurrentApp => System.Windows.Application.Current as App;
    private readonly ChatStorageService _storage;
    private readonly LlmService _llm;
    private readonly ToolRegistry _toolRegistry;
    private readonly AgentLoopService _agentLoop;
    private readonly ModelRouterService _router;
    private readonly object _convLock = new();
    private ChatConversation? _currentConversation;
    private CancellationTokenSource? _streamCts;
    private bool _isStreaming;
    private bool _sidebarVisible = true;
    private string _selectedCategory = ""; // "" = 전체
    private bool _forceClose = false; // 앱 종료 시 진짜 닫기 플래그

    // 스트리밍 UI — 커서 깜빡임 + 로딩 아이콘
    private readonly DispatcherTimer _cursorTimer;
    private bool _cursorVisible = true;
    private TextBlock? _activeStreamText;
    private string _cachedStreamContent = ""; // sb.ToString() 캐시 — 중복 호출 방지
    private TextBlock? _activeAiIcon; // 로딩 펄스 중인 AI 아이콘
    private bool _aiIconPulseStopped;  // 펄스 1회만 중지
    private WorkflowAnalyzerWindow? _analyzerWindow; // 워크플로우 분석기
    private PlanViewerWindow? _planViewerWindow;    // 실행 계획 뷰어
    private bool _userScrolled; // 사용자가 위로 스크롤했는지

    // 경과 시간 표시
    private readonly DispatcherTimer _elapsedTimer;
    private DateTime _streamStartTime;
    private TextBlock? _elapsedLabel;

    // 타이핑 효과
    private readonly DispatcherTimer _typingTimer;
    private int _displayedLength; // 현재 화면에 표시된 글자 수

    private sealed class ConversationMeta
    {
        public string Id { get; init; } = "";
        public string Title { get; init; } = "";
        public string UpdatedAtText { get; init; } = "";
        public bool Pinned { get; init; }
        public string Category { get; init; } = ChatCategory.General;
        public string Symbol { get; init; } = "\uE8BD";
        public string ColorHex { get; init; } = "#6B7280";
        public string Tab { get; init; } = "Chat";
        public DateTime UpdatedAt { get; init; }
        /// <summary>첫 사용자 메시지 요약 (검색용, 최대 100자).</summary>
        public string Preview { get; init; } = "";
        /// <summary>분기 원본 대화 ID. null이면 원본 대화.</summary>
        public string? ParentId { get; init; }
    }

    public ChatWindow(SettingsService settings)
    {
        InitializeComponent();
        _settings = settings;
        _storage = new ChatStorageService();
        _llm = new LlmService(settings);
        _router = new ModelRouterService(settings);
        _toolRegistry = ToolRegistry.CreateDefault();
        _agentLoop = new AgentLoopService(_llm, _toolRegistry, settings)
        {
            Dispatcher = action => System.Windows.Application.Current.Dispatcher.Invoke(action),
            AskPermissionCallback = async (toolName, filePath) =>
            {
                var result = MessageBoxResult.None;
                await System.Windows.Application.Current.Dispatcher.InvokeAsync(() =>
                {
                    result = CustomMessageBox.Show(
                        $"도구 '{toolName}'이(가) 다음 파일에 접근하려 합니다:\n\n{filePath}\n\n허용하시겠습니까?",
                        "AX Agent — 권한 확인",
                        MessageBoxButton.YesNo,
                        MessageBoxImage.Question);
                });
                return result == MessageBoxResult.Yes;
            },
            UserAskCallback = async (question, options, defaultValue) =>
            {
                string? response = null;
                await System.Windows.Application.Current.Dispatcher.InvokeAsync(() =>
                {
                    response = UserAskDialog.Show(question, options, defaultValue);
                });
                return response;
            },
        };

        // Phase 18-A: 백그라운드 에이전트 완료 알림 구독
        if (_toolRegistry.BackgroundAgentService != null)
            _toolRegistry.BackgroundAgentService.AgentCompleted += OnBackgroundAgentCompleted;

        // 설정에서 초기값 로드 (Loaded 전에도 null 방지)
        _selectedMood = settings.Settings.Llm.DefaultMood ?? "modern";
        _folderDataUsage = settings.Settings.Llm.FolderDataUsage ?? "active";

        _cursorTimer = new DispatcherTimer { Interval = TimeSpan.FromMilliseconds(530) };
        _cursorTimer.Tick += CursorTimer_Tick;

        _elapsedTimer = new DispatcherTimer { Interval = TimeSpan.FromSeconds(1) };
        _elapsedTimer.Tick += ElapsedTimer_Tick;

        _typingTimer = new DispatcherTimer { Interval = TimeSpan.FromMilliseconds(12) };
        _typingTimer.Tick += TypingTimer_Tick;

        KeyDown += ChatWindow_KeyDown;
        Loaded += (_, _) =>
        {
            // ── 즉시 필요한 UI 초기화만 동기 실행 ──
            SetupUserInfo();
            _selectedMood = Llm.DefaultMood ?? "modern";
            _folderDataUsage = Llm.FolderDataUsage ?? "active";
            UpdateAnalyzerButtonVisibility();
            UpdateModelLabel();
            UpdatePlanModeUI();
            InitSessionHeaderBar();              // Phase 17-UI-C: 이벤트 연결
            InitSidebarEvents();                 // Phase 17-UI-D: 사이드바 이벤트 연결
            InitInputToolbar();                  // Phase 17-UI-E: 입력 툴바 이벤트 연결
            UpdatePermissionUI();                // Phase 17-UI-C: 헤더 권한 칩 초기화
            InputBox.Focus();
            MessageScroll.ScrollChanged += MessageScroll_ScrollChanged;

            // ── 무거운 작업은 유휴 시점에 비동기 실행 ──
            Dispatcher.BeginInvoke(() =>
            {
                TemplateService.LoadCustomMoods(Llm.CustomMoods);
                BuildTopicButtons();
                RestoreLastConversations();
                RefreshConversationList();

                // 데이터 정리 (디스크 I/O)
                _ = Task.Run(() =>
                {
                    var retention = Llm.RetentionDays;
                    if (retention > 0) _storage.PurgeExpired(retention);
                    _storage.PurgeForDiskSpace();
                });
            }, System.Windows.Threading.DispatcherPriority.ApplicationIdle);

            // 입력 바 포커스 글로우 효과
            var accentBrush = ThemeResourceHelper.Accent(this);
            var borderBrush = ThemeResourceHelper.Border(this);
            InputBox.GotFocus += (_, _) => InputBorder.BorderBrush = accentBrush;
            InputBox.LostFocus += (_, _) => InputBorder.BorderBrush = borderBrush;

            // 드래그 앤 드롭 파일 첨부 + AI 액션 팝업
            InputBorder.AllowDrop = true;
            InputBorder.DragOver += (_, de) =>
            {
                de.Effects = de.Data.GetDataPresent(DataFormats.FileDrop) ? DragDropEffects.Copy : DragDropEffects.None;
                de.Handled = true;
            };
            InputBorder.Drop += (_, de) =>
            {
                if (de.Data.GetData(DataFormats.FileDrop) is string[] files && files.Length > 0)
                {
                    var enableAi = Llm.EnableDragDropAiActions;
                    if (enableAi && files.Length <= 5)
                        ShowDropActionMenu(files);
                    else
                        foreach (var f in files) AddAttachedFile(f);
                }
            };

            // 스킬 시스템 초기화
            if (Llm.EnableSkillSystem)
            {
                SkillService.EnsureSkillFolder();
                SkillService.LoadSkills(Llm.SkillsFolderPath);
            }

            // 슬래시 팝업 네비게이션 버튼
            SlashNavUp.MouseLeftButtonUp += (_, _) =>
            {
                _slashPageOffset = Math.Max(0, _slashPageOffset - SlashPageSize);
                RenderSlashPage();
            };
            SlashNavDown.MouseLeftButtonUp += (_, _) =>
            {
                _slashPageOffset = Math.Min(_slashAllMatches.Count - 1,
                    _slashPageOffset + SlashPageSize);
                RenderSlashPage();
            };

            // 슬래시 명령어 칩 닫기 (× 버튼)
            SlashChipClose.MouseLeftButtonUp += (_, _) =>
            {
                HideSlashChip(restoreText: true);
                InputBox.Focus();
            };

            // InputBox에서 슬래시 팝업 열린 상태로 마우스 휠 → 팝업 스크롤
            InputBox.PreviewMouseWheel += (_, me) =>
            {
                if (!SlashPopup.IsOpen) return;
                me.Handled = true;
                SlashPopup_ScrollByDelta(me.Delta);
            };

            // 탭 UI 초기 상태
            UpdateFolderBar();

            // 호버 애니메이션 — 독립 공간이 있는 버튼에만 Scale 적용
            // (GhostBtn 스타일 버튼은 XAML에서 배경색+opacity 호버 처리)
            ApplyHoverBounceAnimation(BtnModelSelector);
            ApplyHoverBounceAnimation(BtnTemplateSelector, -1.5);
            ApplyHoverScaleAnimation(BtnSend, 1.12);
            ApplyHoverScaleAnimation(BtnStop, 1.12);
        };
        Closed += (_, _) =>
        {
            _streamCts?.Cancel();
            _cursorTimer.Stop();
            _elapsedTimer.Stop();
            _typingTimer.Stop();
            _llm.Dispose();
        };
    }

    /// <summary>
    /// X 버튼으로 닫을 때 창을 숨기기만 합니다 (재사용으로 다음 번 빠르게 열림).
    /// 앱 종료 시에는 ForceClose()를 사용합니다.
    /// </summary>
    protected override void OnClosing(System.ComponentModel.CancelEventArgs e)
    {
        if (!_forceClose)
        {
            e.Cancel = true;
            Hide();
            return;
        }
        base.OnClosing(e);
    }

    /// <summary>앱 종료 시 창을 실제로 닫습니다.</summary>
    public void ForceClose()
    {
        // 현재 대화 저장 + 탭별 마지막 대화 ID를 설정에 영속 저장
        lock (_convLock)
        {
            if (_currentConversation != null && _currentConversation.Messages.Count > 0)
            {
                _tabConversationId[_activeTab] = _currentConversation.Id;
                try { _storage.Save(_currentConversation); } catch (Exception) { /* 대화 저장 실패 — UI 차단 방지 */ }
            }
        }
        SaveLastConversations();

        _forceClose = true;
        Close();
    }
}
