using System.Diagnostics;
using System.IO;
using System.Text.Json;
using System.Text.Json.Serialization;
using System.Windows;
using AxCopilot.SDK;
using AxCopilot.Services;
using AxCopilot.Themes;

namespace AxCopilot.Handlers;

/// <summary>
/// 즐겨찾기(파일/폴더/경로) 핸들러. "fav" 프리픽스로 사용합니다.
/// 자주 사용하는 로컬 파일·폴더 경로를 등록하고 빠르게 실행합니다.
/// 예: fav              → 전체 즐겨찾기 목록
///     fav 보고서        → "보고서" 포함 항목 필터
///     fav add 보고서 C:\work\report.xlsx → 즐겨찾기 추가
///     fav del 보고서    → 즐겨찾기 삭제
/// Enter → 파일/폴더 열기.
/// </summary>
public class FavoriteHandler : IActionHandler
{
    public string? Prefix => "fav";

    public PluginMetadata Metadata => new(
        "Favorite",
        "즐겨찾기 관리 — fav",
        "1.0",
        "AX");

    private static readonly string FavFile = Path.Combine(
        Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData),
        "AxCopilot", "favorites.json");

    private static readonly JsonSerializerOptions JsonOpts = new()
    {
        WriteIndented = true,
        PropertyNameCaseInsensitive = true
    };

    private List<FavEntry> _cache = new();
    private bool _loaded;

    public Task<IEnumerable<LauncherItem>> GetItemsAsync(string query, CancellationToken ct)
    {
        EnsureLoaded();
        var q = query.Trim();

        // add 명령
        if (q.StartsWith("add ", StringComparison.OrdinalIgnoreCase))
        {
            var rest = q[4..].Trim();
            var spaceIdx = rest.IndexOf(' ');
            if (spaceIdx > 0)
            {
                var name = rest[..spaceIdx].Trim();
                var path = rest[(spaceIdx + 1)..].Trim();
                return Task.FromResult<IEnumerable<LauncherItem>>(
                [
                    new LauncherItem(
                        $"즐겨찾기 추가: {name}",
                        $"경로: {path}  ·  Enter로 추가",
                        null, ValueTuple.Create("__ADD__", name, path),
                        Symbol: Symbols.Save)
                ]);
            }
            return Task.FromResult<IEnumerable<LauncherItem>>(
            [
                new LauncherItem(
                    "사용법: fav add [이름] [경로]",
                    "예: fav add 보고서 C:\\work\\report.xlsx",
                    null, null, Symbol: Symbols.Info)
            ]);
        }

        // del 명령
        if (q.StartsWith("del ", StringComparison.OrdinalIgnoreCase))
        {
            var name = q[4..].Trim();
            var found = _cache.FirstOrDefault(b =>
                b.Name.Contains(name, StringComparison.OrdinalIgnoreCase));
            if (found != null)
            {
                return Task.FromResult<IEnumerable<LauncherItem>>(
                [
                    new LauncherItem(
                        $"즐겨찾기 삭제: {found.Name}",
                        $"경로: {found.Path}  ·  Enter로 삭제",
                        null, ValueTuple.Create("__DEL__", found.Name),
                        Symbol: Symbols.Delete)
                ]);
            }
            return Task.FromResult<IEnumerable<LauncherItem>>(
            [
                new LauncherItem($"'{name}'에 해당하는 즐겨찾기 없음", "fav으로 전체 목록 확인",
                    null, null, Symbol: Symbols.Warning)
            ]);
        }

        // 목록/검색
        var filtered = string.IsNullOrWhiteSpace(q)
            ? _cache
            : _cache.Where(b =>
                b.Name.Contains(q, StringComparison.OrdinalIgnoreCase) ||
                b.Path.Contains(q, StringComparison.OrdinalIgnoreCase)).ToList();

        if (!filtered.Any())
        {
            return Task.FromResult<IEnumerable<LauncherItem>>(
            [
                new LauncherItem(
                    _cache.Count == 0 ? "즐겨찾기가 없습니다" : $"'{q}'에 해당하는 즐겨찾기 없음",
                    "fav add [이름] [경로]로 추가하세요",
                    null, null, Symbol: Symbols.Info)
            ]);
        }

        var items = filtered.Select(b =>
        {
            var isDir = Directory.Exists(b.Path);
            var isFile = File.Exists(b.Path);
            var symbol = isDir ? Symbols.Folder : isFile ? Symbols.File : Symbols.Warning;
            var hint = isDir ? "폴더 열기" : isFile ? "파일 열기" : "경로를 찾을 수 없음";
            return new LauncherItem(b.Name, $"{b.Path}  ·  {hint}", null, b.Path, Symbol: symbol);
        }).ToList<LauncherItem>();

        return Task.FromResult<IEnumerable<LauncherItem>>(items);
    }

    public Task ExecuteAsync(LauncherItem item, CancellationToken ct)
    {
        if (item.Data is ValueTuple<string, string, string> add && add.Item1 == "__ADD__")
        {
            AddFav(add.Item2, add.Item3);
            NotificationService.Notify("AX Copilot", $"즐겨찾기 추가: {add.Item2}");
            return Task.CompletedTask;
        }

        if (item.Data is ValueTuple<string, string> del && del.Item1 == "__DEL__")
        {
            RemoveFav(del.Item2);
            NotificationService.Notify("AX Copilot", $"즐겨찾기 삭제: {del.Item2}");
            return Task.CompletedTask;
        }

        if (item.Data is string path)
        {
            if (Directory.Exists(path) || File.Exists(path))
            {
                try { Process.Start(new ProcessStartInfo(path) { UseShellExecute = true }); }
                catch (Exception ex) { LogService.Warn($"즐겨찾기 열기 실패: {ex.Message}"); }
            }
            else
            {
                try { Application.Current?.Dispatcher.Invoke(() => Clipboard.SetText(path)); }
                catch (Exception) { }
            }
        }
        return Task.CompletedTask;
    }

    private void EnsureLoaded()
    {
        if (_loaded) return;
        _loaded = true;
        try
        {
            if (!File.Exists(FavFile)) return;
            _cache = JsonSerializer.Deserialize<List<FavEntry>>(File.ReadAllText(FavFile), JsonOpts) ?? new();
        }
        catch (Exception ex) { LogService.Warn($"즐겨찾기 로드 실패: {ex.Message}"); }
    }

    private void AddFav(string name, string path)
    {
        EnsureLoaded();
        _cache.RemoveAll(b => b.Name.Equals(name, StringComparison.OrdinalIgnoreCase));
        _cache.Insert(0, new FavEntry { Name = name, Path = path });
        Save();
    }

    private void RemoveFav(string name)
    {
        EnsureLoaded();
        _cache.RemoveAll(b => b.Name.Equals(name, StringComparison.OrdinalIgnoreCase));
        Save();
    }

    private void Save()
    {
        try
        {
            Directory.CreateDirectory(Path.GetDirectoryName(FavFile)!);
            File.WriteAllText(FavFile, JsonSerializer.Serialize(_cache, JsonOpts));
        }
        catch (Exception ex) { LogService.Warn($"즐겨찾기 저장 실패: {ex.Message}"); }
    }

    private class FavEntry
    {
        [JsonPropertyName("name")] public string Name { get; set; } = "";
        [JsonPropertyName("path")] public string Path { get; set; } = "";
    }
}
