using System.ComponentModel;
using System.Diagnostics;
using System.IO;
using System.Runtime.CompilerServices;
using System.Windows;
using AxCopilot.Models;
using AxCopilot.SDK;
using AxCopilot.Services;

namespace AxCopilot.ViewModels;

public partial class LauncherViewModel
{
    // ─── 단축키 지원 메서드 ──────────────────────────────────────────────────

    /// <summary>선택된 항목의 경로를 클립보드에 복사</summary>
    public bool CopySelectedPath()
    {
        if (SelectedItem?.Data is IndexEntry entry)
        {
            var path = Path.GetFileName(Environment.ExpandEnvironmentVariables(entry.Path));
            Application.Current.Dispatcher.Invoke(() => Clipboard.SetText(path));
            return true;
        }
        return false;
    }

    /// <summary>선택된 항목의 전체 경로를 클립보드에 복사</summary>
    public bool CopySelectedFullPath()
    {
        if (SelectedItem?.Data is IndexEntry entry)
        {
            var path = Environment.ExpandEnvironmentVariables(entry.Path);
            Application.Current.Dispatcher.Invoke(() => Clipboard.SetText(path));
            return true;
        }
        return false;
    }

    /// <summary>선택된 항목을 탐색기에서 열기</summary>
    public bool OpenSelectedInExplorer()
    {
        if (SelectedItem?.Data is IndexEntry entry)
        {
            var path = Environment.ExpandEnvironmentVariables(entry.Path);
            if (File.Exists(path))
                Process.Start("explorer.exe", $"/select,\"{path}\"");
            else if (Directory.Exists(path))
                Process.Start("explorer.exe", $"\"{path}\"");
            return true;
        }
        return false;
    }

    /// <summary>선택된 항목을 관리자 권한으로 실행</summary>
    public bool RunSelectedAsAdmin()
    {
        if (SelectedItem?.Data is IndexEntry entry)
        {
            var path = Environment.ExpandEnvironmentVariables(entry.Path);
            try
            {
                Process.Start(new ProcessStartInfo(path)
                    { UseShellExecute = true, Verb = "runas" });
                return true;
            }
            catch (Exception ex) { LogService.Warn($"관리자 실행 취소: {ex.Message}"); }
        }
        return false;
    }

    /// <summary>선택된 항목의 속성 창 열기</summary>
    public bool ShowSelectedProperties()
    {
        if (SelectedItem?.Data is IndexEntry entry)
        {
            var path = Environment.ExpandEnvironmentVariables(entry.Path);
            try
            {
                Process.Start(new ProcessStartInfo(path)
                    { UseShellExecute = true, Verb = "properties" });
                return true;
            }
            catch (Exception)
            {
                // properties verb 미지원 시 탐색기에서 선택
                Process.Start("explorer.exe", $"/select,\"{path}\"");
                return true;
            }
        }
        return false;
    }

    /// <summary>최근 기록에서 항목 삭제 (Delete 키용)</summary>
    public bool RemoveSelectedFromRecent()
    {
        if (SelectedItem == null || Results.Count == 0) return false;

        var idx = Results.IndexOf(SelectedItem);
        Results.Remove(SelectedItem);

        if (Results.Count > 0)
            SelectedItem = Results[Math.Min(idx, Results.Count - 1)];
        else
            SelectedItem = null;

        return true;
    }

    /// <summary>입력창 초기화</summary>
    public void ClearInput()
    {
        InputText = "";
    }

    /// <summary>첫 번째 결과 항목 선택</summary>
    public void SelectFirst()
    {
        if (Results.Count > 0) SelectedItem = Results[0];
    }

    /// <summary>마지막 결과 항목 선택</summary>
    public void SelectLast()
    {
        if (Results.Count > 0) SelectedItem = Results[^1];
    }

    /// <summary>현재 선택된 파일/폴더 항목을 즐겨찾기에 추가하거나 제거합니다.</summary>
    /// <returns>(추가됐으면 true, 제거됐으면 false, 대상 없으면 null)</returns>
    public bool? ToggleFavorite()
    {
        if (SelectedItem?.Data is not IndexEntry entry) return null;

        var path = Environment.ExpandEnvironmentVariables(entry.Path);
        var name = Path.GetFileNameWithoutExtension(path);
        if (string.IsNullOrWhiteSpace(name)) name = Path.GetFileName(path);

        var favFile = Path.Combine(
            Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
            "AxCopilot", "favorites.json");

        try
        {
            var opts = new System.Text.Json.JsonSerializerOptions
                { WriteIndented = true, PropertyNameCaseInsensitive = true };

            List<FavJson> list = new();
            if (File.Exists(favFile))
                list = System.Text.Json.JsonSerializer.Deserialize<List<FavJson>>(
                    File.ReadAllText(favFile), opts) ?? new();

            var existing = list.FirstOrDefault(f =>
                f.Path.Equals(path, StringComparison.OrdinalIgnoreCase));

            if (existing != null)
            {
                list.Remove(existing);
                Directory.CreateDirectory(Path.GetDirectoryName(favFile)!);
                File.WriteAllText(favFile, System.Text.Json.JsonSerializer.Serialize(list, opts));
                return false; // 제거됨
            }
            else
            {
                list.Insert(0, new FavJson { Name = name, Path = path });
                Directory.CreateDirectory(Path.GetDirectoryName(favFile)!);
                File.WriteAllText(favFile, System.Text.Json.JsonSerializer.Serialize(list, opts));
                return true;  // 추가됨
            }
        }
        catch (Exception ex)
        {
            LogService.Warn($"즐겨찾기 토글 실패: {ex.Message}");
            return null;
        }
    }

    /// <summary>선택 항목의 디렉터리에서 터미널을 열기.</summary>
    /// <returns>성공 여부</returns>
    public bool OpenSelectedInTerminal()
    {
        string dir;
        if (SelectedItem?.Data is IndexEntry entry)
        {
            var path = Environment.ExpandEnvironmentVariables(entry.Path);
            dir = Directory.Exists(path) ? path : Path.GetDirectoryName(path) ?? path;
        }
        else
        {
            dir = Environment.GetFolderPath(Environment.SpecialFolder.UserProfile);
        }

        try { Process.Start("wt.exe", $"-d \"{dir}\""); return true; }
        catch (Exception)
        {
            try { Process.Start("cmd.exe", $"/k cd /d \"{dir}\""); return true; }
            catch (Exception ex) { LogService.Warn($"터미널 열기 실패: {ex.Message}"); return false; }
        }
    }

    /// <summary>다운로드 폴더를 cd 프리픽스로 탐색합니다.</summary>
    public void NavigateToDownloads()
    {
        var downloads = Path.Combine(
            Environment.GetFolderPath(Environment.SpecialFolder.UserProfile), "Downloads");
        InputText = $"cd {downloads}";
    }

    // 즐겨찾기 직렬화용 내부 레코드
    private sealed class FavJson
    {
        [System.Text.Json.Serialization.JsonPropertyName("name")]
        public string Name { get; set; } = "";
        [System.Text.Json.Serialization.JsonPropertyName("path")]
        public string Path { get; set; } = "";
    }

    // ─── 클립보드 병합 ────────────────────────────────────────────────────────

    public void ToggleMergeItem(LauncherItem? item)
    {
        if (item?.Data is not ClipboardEntry entry || !entry.IsText) return;

        if (!_mergeQueue.Remove(entry))
            _mergeQueue.Add(entry);

        OnPropertyChanged(nameof(MergeCount));
        OnPropertyChanged(nameof(ShowMergeHint));
        OnPropertyChanged(nameof(MergeHintText));
    }

    /// <summary>선택된 항목들을 줄바꿈으로 합쳐 클립보드에 복사</summary>
    public void ExecuteMerge()
    {
        if (_mergeQueue.Count == 0) return;

        // 선택 순서 보존: Results에서 보이는 순서 기준
        var ordered = Results
            .Where(r => r.Data is ClipboardEntry e && _mergeQueue.Contains(e))
            .Select(r => ((ClipboardEntry)r.Data!).Text)
            .ToList();

        if (ordered.Count == 0)
            ordered = _mergeQueue.Select(e => e.Text).ToList();

        var merged = string.Join("\n", ordered);
        try { Application.Current.Dispatcher.Invoke(() => Clipboard.SetText(merged)); }
        catch (Exception ex) { LogService.Warn($"병합 클립보드 실패: {ex.Message}"); }

        ClearMerge();
        CloseRequested?.Invoke(this, EventArgs.Empty);
        LogService.Info($"클립보드 병합: {ordered.Count}개 항목");
    }

    public void ClearMerge()
    {
        _mergeQueue.Clear();
        OnPropertyChanged(nameof(MergeCount));
        OnPropertyChanged(nameof(ShowMergeHint));
        OnPropertyChanged(nameof(MergeHintText));
    }

    // ─── INotifyPropertyChanged ───────────────────────────────────────────────

    public event PropertyChangedEventHandler? PropertyChanged;
    protected void OnPropertyChanged([CallerMemberName] string? name = null)
        => PropertyChanged?.Invoke(this, new PropertyChangedEventArgs(name));
}

// ─── 파일 액션 데이터 타입 ────────────────────────────────────────────────────

public enum FileAction { CopyPath, CopyFullPath, OpenExplorer, RunAsAdmin, OpenTerminal, ShowProperties, Rename, DeleteToRecycleBin }

public record FileActionData(string Path, FileAction Action);
