using System.Runtime.InteropServices;
using System.Windows;
using System.Windows.Input;
using System.Windows.Interop;
using AxCopilot.Services;

namespace AxCopilot.Views;

public partial class LauncherWindow
{
    // ─── Shell32 휴지통 삭제 ────────────────────────────────────────────────

    [StructLayout(LayoutKind.Sequential, CharSet = CharSet.Unicode)]
    private struct SHFILEOPSTRUCT
    {
        public IntPtr hwnd;
        public uint   wFunc;
        [MarshalAs(UnmanagedType.LPWStr)] public string pFrom;
        [MarshalAs(UnmanagedType.LPWStr)] public string? pTo;
        public ushort fFlags;
        [MarshalAs(UnmanagedType.Bool)] public bool fAnyOperationsAborted;
        public IntPtr hNameMappings;
        [MarshalAs(UnmanagedType.LPWStr)] public string? lpszProgressTitle;
    }

    [DllImport("shell32.dll", CharSet = CharSet.Unicode)]
    private static extern int SHFileOperation(ref SHFILEOPSTRUCT lpFileOp);

    private const uint   FO_DELETE          = 0x0003;
    private const ushort FOF_ALLOWUNDO      = 0x0040;
    private const ushort FOF_NOCONFIRMATION = 0x0010;
    private const ushort FOF_SILENT         = 0x0004;

    /// <summary>파일·폴더를 Windows 휴지통으로 보냅니다.</summary>
    private void SendToRecycleBin(string path)
    {
        // pFrom은 null-terminated + 추가 null 필요
        var op = new SHFILEOPSTRUCT
        {
            hwnd   = new WindowInteropHelper(this).Handle,
            wFunc  = FO_DELETE,
            pFrom  = path + '\0',
            fFlags = FOF_ALLOWUNDO | FOF_NOCONFIRMATION | FOF_SILENT,
        };
        int result = SHFileOperation(ref op);
        if (result != 0)
            throw new System.ComponentModel.Win32Exception(result, $"SHFileOperation 실패 (코드 {result})");
    }

    // ─── 대형 텍스트 / 클립보드 외부 뷰어 ──────────────────────────────────

    private void ShowLargeType()
    {
        // 클립보드 항목 → 시스템 클립보드에 자동 복사 + 외부 앱에서 열기
        if (_vm.SelectedItem?.Data is Services.ClipboardEntry clipEntry)
        {
            try
            {
                // 자동 클립보드 복사 억제 (히스토리 중복 방지)
                CurrentApp?.ClipboardHistoryService?.SuppressNextCapture();

                if (!clipEntry.IsText && clipEntry.Image != null)
                {
                    // 원본 이미지가 있으면 원본 사용, 없으면 썸네일 사용
                    var originalImg = Services.ClipboardHistoryService.LoadOriginalImage(clipEntry.OriginalImagePath);
                    var imgToUse = originalImg ?? clipEntry.Image;

                    // 시스템 클립보드에 원본 복사
                    Clipboard.SetImage(imgToUse);

                    // 이미지: PNG로 저장 → 기본 이미지 뷰어
                    string path;
                    if (!string.IsNullOrEmpty(clipEntry.OriginalImagePath) &&
                        System.IO.File.Exists(clipEntry.OriginalImagePath))
                    {
                        path = clipEntry.OriginalImagePath; // 원본 파일 직접 열기
                    }
                    else
                    {
                        path = Services.TempFileService.CreateTempFile("clip_image", ".png");
                        var encoder = new System.Windows.Media.Imaging.PngBitmapEncoder();
                        encoder.Frames.Add(System.Windows.Media.Imaging.BitmapFrame.Create(imgToUse));
                        using var fs = new System.IO.FileStream(path, System.IO.FileMode.Create);
                        encoder.Save(fs);
                    }
                    System.Diagnostics.Process.Start(new System.Diagnostics.ProcessStartInfo(path) { UseShellExecute = true });
                }
                else if (!string.IsNullOrEmpty(clipEntry.Text))
                {
                    // 시스템 클립보드에 텍스트 복사
                    Clipboard.SetText(clipEntry.Text);

                    // 텍스트: txt로 저장 → 메모장
                    var path = Services.TempFileService.CreateTempFile("clip_text", ".txt");
                    System.IO.File.WriteAllText(path, clipEntry.Text, System.Text.Encoding.UTF8);
                    System.Diagnostics.Process.Start(new System.Diagnostics.ProcessStartInfo("notepad.exe", $"\"{path}\"") { UseShellExecute = true });
                }
            }
            catch (Exception ex)
            {
                Services.LogService.Warn($"클립보드 외부 뷰어 실패: {ex.Message}");
            }
            return;
        }

        var text = _vm.GetLargeTypeText();
        if (string.IsNullOrWhiteSpace(text)) return;
        new LargeTypeWindow(text).Show();
    }

    // ─── 마우스 클릭 처리 ───────────────────────────────────────────────────

    /// <summary>이미 선택된 아이템을 클릭하면 Execute, 아직 선택되지 않은 아이템 클릭은 선택만.</summary>
    private SDK.LauncherItem? _lastClickedItem;
    private DateTime _lastClickTime;

    private void ResultList_PreviewMouseLeftButtonUp(object sender, MouseButtonEventArgs e)
    {
        // 클릭한 ListViewItem 찾기
        var dep = e.OriginalSource as DependencyObject;
        while (dep != null && dep is not System.Windows.Controls.ListViewItem)
            dep = System.Windows.Media.VisualTreeHelper.GetParent(dep);
        if (dep is not System.Windows.Controls.ListViewItem lvi) return;

        var clickedItem = lvi.Content as SDK.LauncherItem;
        if (clickedItem == null) return;

        // Phase L2-5: Ctrl+Click → 클립보드 히스토리 모드에서 다중 선택 토글
        if ((Keyboard.Modifiers & ModifierKeys.Control) != 0 && _vm.IsClipboardMode)
        {
            _vm.ToggleMergeItem(clickedItem);
            e.Handled = true;
            return;
        }

        var now = DateTime.UtcNow;
        var timeSinceLastClick = (now - _lastClickTime).TotalMilliseconds;

        if (_lastClickedItem == clickedItem && timeSinceLastClick < 600)
        {
            // 같은 아이템을 짧은 간격으로 재클릭 → 액션 모드 또는 실행
            if (!_vm.IsActionMode && _vm.CanEnterActionMode())
            {
                _vm.EnterActionMode(clickedItem);
                e.Handled = true;
            }
            else
            {
                _ = _vm.ExecuteSelectedAsync();
                e.Handled = true;
            }
            _lastClickedItem = null;
            return;
        }

        // 첫 번째 클릭 → 선택만
        _lastClickedItem = clickedItem;
        _lastClickTime = now;
    }

    private void ResultList_MouseDoubleClick(object sender, MouseButtonEventArgs e)
    {
        _ = _vm.ExecuteSelectedAsync();
    }

    // ─── F3 QuickLook 토글 ────────────────────────────────────────────────

    /// <summary>현재 열린 QuickLook 창 참조 (토글/닫기 추적용)</summary>
    private QuickLookWindow? _quickLookWindow;

    /// <summary>
    /// F3 빠른 미리보기 토글.
    /// 이미 열려 있으면 닫고, 없으면 선택된 파일/폴더로 미리보기 창을 엽니다.
    /// </summary>
    internal void ToggleQuickLook()
    {
        // 이미 열린 창이 있으면 닫기 (토글)
        if (_quickLookWindow != null)
        {
            _quickLookWindow.Close();
            _quickLookWindow = null;
            return;
        }

        var selected = _vm.SelectedItem;
        string? path = null;

        if (selected?.Data is Services.IndexEntry indexEntry)
            path = Environment.ExpandEnvironmentVariables(indexEntry.Path);

        if (string.IsNullOrEmpty(path)) return;
        if (!System.IO.File.Exists(path) && !System.IO.Directory.Exists(path)) return;

        // 런처 창 오른쪽에 배치 (화면 경계 고려)
        var qlLeft = Left + ActualWidth + 8;
        var qlTop  = Top;

        // 화면 오른쪽 여백 확인 (화면 밖으로 나가면 왼쪽에 배치)
        var screen = System.Windows.Forms.Screen.FromHandle(
            new System.Windows.Interop.WindowInteropHelper(this).Handle);
        if (qlLeft + 400 > screen.WorkingArea.Right)
            qlLeft = Left - 408;

        _quickLookWindow = new QuickLookWindow(path, this)
        {
            Left = qlLeft,
            Top  = qlTop
        };
        _quickLookWindow.Closed += (_, _) => _quickLookWindow = null;
        _quickLookWindow.Show();
    }

    // ─── 창 이벤트 / 스크롤 / 알림 ─────────────────────────────────────────

    private void Window_Deactivated(object sender, EventArgs e)
    {
        // 위치 기억 설정이 켜진 경우 현재 위치 저장
        var app = System.Windows.Application.Current as App;
        var s = app?.SettingsService?.Settings;
        if (s?.Launcher.RememberPosition == true && IsVisible && Left >= 0 && Top >= 0)
        {
            s.Launcher.LastLeft = Left;
            s.Launcher.LastTop  = Top;
            _ = Task.Run(() => { try { app!.SettingsService!.Save(); } catch { } });
        }
        // 설정 › 기능 › "포커스 잃으면 닫기"가 켜진 경우에만 자동 숨김
        if (_vm.CloseOnFocusLost) Hide();
    }

    private void Window_IsVisibleChanged(object sender, DependencyPropertyChangedEventArgs e)
    {
        // 런처 숨김 시 QuickLook도 함께 닫기
        if (!(bool)e.NewValue)
        {
            _quickLookWindow?.Close();
            _quickLookWindow = null;
        }
    }

    private void ScrollToSelected()
    {
        if (_vm.SelectedItem != null)
            ResultList.ScrollIntoView(_vm.SelectedItem);
    }

    private void ShowNotification(string message)
    {
        // 시스템 트레이 토스트 알림 표시
        // App.xaml.cs의 TrayIcon을 통해 처리
    }

    // ─── 퀵 액션 칩 클릭 ──────────────────────────────────────────────────────

    /// <summary>
    /// 입력창 아래 최근 실행 칩 클릭 시 — 경로를 즉시 실행하고 런처를 닫습니다.
    /// </summary>
    private async void QuickActionChip_Click(object sender, MouseButtonEventArgs e)
    {
        if (((System.Windows.FrameworkElement)sender).DataContext
                is not Models.QuickActionChip chip) return;

        var expanded = Environment.ExpandEnvironmentVariables(chip.Path);
        Hide(); // 창 먼저 숨겨 체감 속도 확보

        try
        {
            await Task.Run(() =>
                System.Diagnostics.Process.Start(
                    new System.Diagnostics.ProcessStartInfo(expanded)
                    { UseShellExecute = true }));
        }
        catch (Exception ex)
        {
            Services.LogService.Error($"퀵 액션 실행 실패: {expanded} - {ex.Message}");
        }

        // 사용 통계 기록 (비동기)
        _ = Task.Run(() => Services.UsageRankingService.RecordExecution(chip.Path));
    }
}
