using System.Windows;
using System.Windows.Forms;
using AxCopilot.Core;
using AxCopilot.Services;
using AxCopilot.ViewModels;
using AxCopilot.Views;

namespace AxCopilot;

public partial class App
{
    // ─── 설정창 / ChatWindow ─────────────────────────────────────────────

    private void SetupTrayIcon(PluginHost pluginHost, SettingsService settings)
    {
        _trayIcon = new NotifyIcon
        {
            Text    = "AX Copilot",
            Visible = true,
            Icon    = LoadAppIcon()
        };

        // ─── WPF 커스텀 트레이 메뉴 구성 ──────────────────────────────────
        _trayMenu = new Views.TrayMenuWindow();
        _trayMenu
            .AddItem("\uE7C5", "AX Commander 호출하기", () =>
                Dispatcher.Invoke(() => _launcher?.Show()))
            .AddItem("\uE8BD", "AX Agent 대화하기", () =>
                Dispatcher.Invoke(() => OpenAiChat()), out var aiTrayItem)
            .AddItem("\uE8A7", "독 바 표시", () =>
                Dispatcher.Invoke(() => ToggleDockBar()))
            .AddSeparator()
            .AddItem("\uE72C", "플러그인 재로드", () =>
            {
                pluginHost.Reload();
                _trayIcon!.ShowBalloonTip(2000, "AX Copilot", "플러그인이 재로드되었습니다.", ToolTipIcon.None);
            })
            .AddItem("\uE838", "로그 폴더 열기", () =>
            {
                var logDir = System.IO.Path.Combine(
                    Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
                    "AxCopilot", "logs");
                System.Diagnostics.Process.Start(new System.Diagnostics.ProcessStartInfo("explorer.exe", logDir)
                    { UseShellExecute = true });
            })
            .AddItem("\uE9D9", "사용 통계", () =>
                Dispatcher.Invoke(() => new StatisticsWindow().Show()))
            .AddItem("\uE736", "사용 가이드 문서보기", () =>
            {
                try { Dispatcher.Invoke(() => new Views.GuideViewerWindow().Show()); }
                catch (Exception ex) { LogService.Error($"사용 가이드 열기 실패: {ex.Message}"); }
            })
            .AddSeparator()
            .AddToggleItem("\uE82F", "Windows 시작 시 자동 실행", IsAutoStartEnabled(),
                isChecked => SetAutoStart(isChecked), out _, out _)
            .AddSeparator()
            .AddItem("\uE713", "설정", () =>
                Dispatcher.Invoke(OpenSettings))
            .AddItem("\uE946", "개발 정보", () =>
                Dispatcher.Invoke(() => new AboutWindow().Show()))
            .AddItem("\uE711", "종료", () =>
            {
                _inputListener?.Dispose();
                _trayIcon?.Dispose();
                Shutdown();
            });

        // AI 기능 활성화 여부에 따라 메뉴 항목 가시성 동적 업데이트
        _trayMenu.Opening += () =>
        {
            aiTrayItem.Visibility = settings.Settings.AiEnabled
                ? System.Windows.Visibility.Visible
                : System.Windows.Visibility.Collapsed;
        };

        // 우클릭 → WPF 메뉴 표시, 좌클릭 → 런처 토글
        _trayIcon.MouseClick += (_, e) =>
        {
            if (e.Button == System.Windows.Forms.MouseButtons.Left)
                Dispatcher.Invoke(() => _launcher?.Show());
            else if (e.Button == System.Windows.Forms.MouseButtons.Right)
                Dispatcher.Invoke(() => _trayMenu?.ShowWithUpdate());
        };

        // 타이머/알람 풍선 알림 서비스 연결
        NotificationService.Initialize((title, msg) =>
        {
            Dispatcher.Invoke(() =>
                _trayIcon?.ShowBalloonTip(4000, title, msg, ToolTipIcon.None));
        });
    }

    /// <summary>ChatWindow 등 외부에서 설정 창을 여는 공개 메서드.</summary>
    public void OpenSettingsFromChat() => Dispatcher.Invoke(OpenSettings);

    /// <summary>AX Agent 창 열기 (트레이 메뉴 등에서 호출).</summary>
    private Views.ChatWindow? _chatWindow;

    /// <summary>
    /// ChatWindow를 백그라운드에서 미리 생성합니다 (앱 시작 후 저우선순위로 호출).
    /// 이후 OpenAiChat() 시 창 생성 비용 없이 즉시 Show/Activate만 수행합니다.
    /// </summary>
    internal void PrewarmChatWindow()
    {
        if (_chatWindow != null || _settings == null) return;
        _chatWindow = new Views.ChatWindow(_settings);
    }

    private void OpenAiChat()
    {
        if (_settings == null) return;
        if (_chatWindow == null)
        {
            _chatWindow = new Views.ChatWindow(_settings);
        }
        _chatWindow.Show();
        _chatWindow.Activate();
    }

    public void ToggleDockBar()
    {
        if (_dockBar != null && _dockBar.IsVisible)
        {
            _dockBar.Hide();
            return;
        }

        if (_dockBar == null)
        {
            _dockBar = new DockBarWindow();
            _dockBar.OnQuickSearch = query =>
            {
                if (_launcher == null) return;
                _launcher.Show();
                _launcher.Activate(); // 독 바 뒤가 아닌 전면에 표시
                if (!string.IsNullOrEmpty(query))
                    Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Input,
                        () => _launcher.SetInputText(query));
            };
            _dockBar.OnCapture = async () =>
            {
                WindowTracker.Capture();
                if (_captureHandler != null)
                    await _captureHandler.CaptureDirectAsync("region");
            };
            _dockBar.OnOpenAgent = () =>
            {
                if (_launcher == null) return;
                _launcher.Show();
                Dispatcher.BeginInvoke(System.Windows.Threading.DispatcherPriority.Input,
                    () => _launcher.SetInputText("!"));
            };
        }
        var launcher = _settings?.Settings.Launcher;
        var dockItems = launcher?.DockBarItems ?? new() { "launcher", "clipboard", "capture", "agent", "clock", "cpu" };
        _dockBar.BuildFromSettings(dockItems);

        // Phase L3-7: 독 바 위치 변경 시 모니터별로 저장
        _dockBar.OnPositionChanged = (left, top) =>
        {
            if (_settings == null) return;
            var lnch = _settings.Settings.Launcher;
            lnch.DockBarLeft = left;
            lnch.DockBarTop  = top;

            // 현재 독 바가 속한 모니터 디바이스 이름으로 위치 기억
            var deviceName = GetMonitorDeviceNameAt(_dockBar, left, top);
            if (deviceName != null)
                lnch.MonitorDockPositions[deviceName] = new[] { left, top };

            _settings.Save();
        };

        _dockBar.Show();

        // Phase L3-7: 저장 위치 유효성 검사 — 연결이 끊긴 모니터면 중앙 하단으로 리셋
        var savedLeft = launcher?.DockBarLeft ?? -1;
        var savedTop  = launcher?.DockBarTop  ?? -1;
        if (!IsDockPositionOnAnyMonitor(savedLeft, savedTop))
        {
            LogService.Info("[MultiMonitor] 독 바 저장 위치가 연결된 모니터 밖 → 중앙 하단으로 초기화");
            savedLeft = -1;
            savedTop  = -1;
        }

        _dockBar.ApplySettings(
            launcher?.DockBarOpacity ?? 0.92,
            savedLeft,
            savedTop,
            launcher?.DockBarRainbowGlow ?? false);
    }

    // ─── Phase L3-7: 다중 모니터 헬퍼 ─────────────────────────────────────

    /// <summary>
    /// WPF 논리 좌표를 물리적 좌표로 변환하여 해당 모니터의 디바이스 이름을 반환합니다.
    /// </summary>
    private static string? GetMonitorDeviceNameAt(
        System.Windows.Media.Visual? visual, double wpfLeft, double wpfTop)
    {
        try
        {
            System.Drawing.Point physPt;
            var src = visual != null ? PresentationSource.FromVisual(visual) : null;
            if (src?.CompositionTarget != null)
            {
                var m  = src.CompositionTarget.TransformToDevice;  // logical→physical
                var pt = m.Transform(new System.Windows.Point(wpfLeft + 10, wpfTop + 10));
                physPt = new System.Drawing.Point((int)pt.X, (int)pt.Y);
            }
            else
            {
                physPt = new System.Drawing.Point((int)wpfLeft + 10, (int)wpfTop + 10);
            }
            return System.Windows.Forms.Screen.FromPoint(physPt).DeviceName;
        }
        catch { return null; }
    }

    /// <summary>
    /// 저장된 독 바 위치(WPF 논리 좌표)가 현재 연결된 모니터 중 하나에 있는지 검사합니다.
    /// 모니터가 분리되거나 해상도가 변경되어 위치가 화면 밖에 있으면 false를 반환합니다.
    /// </summary>
    private static bool IsDockPositionOnAnyMonitor(double left, double top)
    {
        if (left < 0 || top < 0) return false;  // -1 기본값은 항상 재계산 대상
        try
        {
            // 참고: WPF 논리 좌표와 물리적 픽셀의 차이는 DPI에 따라 다르나
            //       "화면 밖인지" 판단에는 근사 비교로 충분합니다.
            return System.Windows.Forms.Screen.AllScreens
                .Any(s => left >= s.Bounds.Left  && left < s.Bounds.Right
                       && top  >= s.Bounds.Top   && top  < s.Bounds.Bottom);
        }
        catch { return true; }  // 오류 시 보수적으로 true (위치 유지)
    }

    /// <summary>독 바를 현재 설정으로 즉시 새로고침합니다.</summary>
    public void RefreshDockBar()
    {
        if (_dockBar == null || !_dockBar.IsVisible) return;
        var launcher = _settings?.Settings.Launcher;
        var dockItems = launcher?.DockBarItems ?? new() { "launcher", "clipboard", "capture", "agent", "clock", "cpu" };
        _dockBar.BuildFromSettings(dockItems);
        _dockBar.ApplySettings(
            launcher?.DockBarOpacity ?? 0.92,
            launcher?.DockBarLeft ?? -1,
            launcher?.DockBarTop ?? -1,
            launcher?.DockBarRainbowGlow ?? false);
    }

    private void OpenSettings()
    {
        if (_settingsWindow != null && _settingsWindow.IsVisible)
        {
            _settingsWindow.Activate();
            return;
        }

        if (_settings == null || _launcher == null) return;

        var vm = new ViewModels.SettingsViewModel(_settings);

        // 미리보기 콜백: 현재 편집 중인 색상(vm.ColorRows)으로 런처에 즉시 반영
        void PreviewCallback(string themeKey)
        {
            if (themeKey == "custom")
            {
                var tempColors = new AxCopilot.Models.CustomThemeColors();
                foreach (var row in vm.ColorRows)
                {
                    var prop = typeof(AxCopilot.Models.CustomThemeColors).GetProperty(row.Property);
                    prop?.SetValue(tempColors, row.Hex);
                }
                _launcher.ApplyTheme(themeKey, tempColors);
            }
            else
            {
                _launcher.ApplyTheme(themeKey, _settings.Settings.Launcher.CustomTheme);
            }
        }

        // 취소/X 닫기 콜백: 파일에 저장된 원본 설정으로 복원
        void RevertCallback()
        {
            _launcher.ApplyTheme(
                _settings.Settings.Launcher.Theme ?? "system",
                _settings.Settings.Launcher.CustomTheme);
        }

        _settingsWindow = new Views.SettingsWindow(vm, PreviewCallback, RevertCallback)
        {
            // 핫키 녹화 중 글로벌 핫키 일시 정지
            SuspendHotkeyCallback = suspend =>
            {
                if (_inputListener != null)
                    _inputListener.SuspendHotkey = suspend;
            }
        };

        // 저장 완료 시 InputListener 핫키 갱신 + 알림 타이머 재시작
        vm.SaveCompleted += (_, _) =>
        {
            if (_inputListener != null && _settings != null)
            {
                _inputListener.UpdateHotkey(_settings.Settings.Hotkey);
                _inputListener.UpdateCaptureHotkey(
                    _settings.Settings.ScreenCapture.GlobalHotkey,
                    _settings.Settings.ScreenCapture.GlobalHotkeyEnabled);
                _inputListener.UpdateCustomHotkeys(_settings.Settings.CustomHotkeys);
            }
            _worktimeReminder?.RestartTimer();
        };

        _settingsWindow.Show();
    }
}
