using System.Diagnostics;
using AxCopilot.Models;
using AxCopilot.SDK;
using AxCopilot.Services;
using AxCopilot.Themes;

namespace AxCopilot.Handlers;

/// <summary>
/// L6-2: 런처 매크로 핸들러. "macro" 프리픽스로 사용합니다.
///
/// 예: macro                  → 매크로 목록
///     macro 이름              → 이름으로 필터
///     macro new               → 새 매크로 편집기 열기
///     macro edit 이름         → 기존 매크로 편집
///     macro del 이름          → 매크로 삭제
///     macro play 이름         → 즉시 실행
/// Enter로 선택한 매크로를 실행합니다.
/// </summary>
public class MacroHandler : IActionHandler
{
    private readonly SettingsService _settings;

    public MacroHandler(SettingsService settings) { _settings = settings; }

    public string? Prefix => "macro";

    public PluginMetadata Metadata => new(
        "Macro",
        "런처 매크로 — macro",
        "1.0",
        "AX");

    // ─── 항목 목록 ──────────────────────────────────────────────────────────
    public Task<IEnumerable<LauncherItem>> GetItemsAsync(string query, CancellationToken ct)
    {
        var q     = query.Trim();
        var parts = q.Split(' ', 2, StringSplitOptions.TrimEntries);
        var cmd   = parts.Length > 0 ? parts[0].ToLowerInvariant() : "";

        if (cmd == "new")
        {
            return Task.FromResult<IEnumerable<LauncherItem>>(new[]
            {
                new LauncherItem("새 매크로 만들기",
                    "편집기에서 단계별 실행 시퀀스를 설정합니다",
                    null, "__new__", Symbol: "\uE710")
            });
        }

        if (cmd == "edit" && parts.Length > 1)
        {
            return Task.FromResult<IEnumerable<LauncherItem>>(new[]
            {
                new LauncherItem($"'{parts[1]}' 매크로 편집", "편집기 열기",
                    null, $"__edit__{parts[1]}", Symbol: "\uE70F")
            });
        }

        if ((cmd == "del" || cmd == "delete") && parts.Length > 1)
        {
            return Task.FromResult<IEnumerable<LauncherItem>>(new[]
            {
                new LauncherItem($"'{parts[1]}' 매크로 삭제",
                    "Enter로 삭제 확인",
                    null, $"__del__{parts[1]}", Symbol: Symbols.Delete)
            });
        }

        if (cmd == "play" && parts.Length > 1)
        {
            var entry = _settings.Settings.Macros
                .FirstOrDefault(m => m.Name.Equals(parts[1], StringComparison.OrdinalIgnoreCase));
            if (entry != null)
            {
                return Task.FromResult<IEnumerable<LauncherItem>>(new[]
                {
                    new LauncherItem($"[{entry.Name}] 매크로 실행",
                        $"{entry.Steps.Count}단계  ·  Enter로 즉시 실행",
                        null, entry, Symbol: "\uE768")
                });
            }
        }

        // 목록
        var macros = _settings.Settings.Macros;
        var filter = q.ToLowerInvariant();
        var items  = new List<LauncherItem>();

        foreach (var m in macros)
        {
            if (!string.IsNullOrEmpty(filter) &&
                !m.Name.Contains(filter, StringComparison.OrdinalIgnoreCase) &&
                !m.Description.Contains(filter, StringComparison.OrdinalIgnoreCase))
                continue;

            var preview = m.Steps.Count == 0
                ? "단계 없음"
                : string.Join(" → ", m.Steps.Take(3).Select(s => string.IsNullOrWhiteSpace(s.Label) ? s.Target : s.Label))
                  + (m.Steps.Count > 3 ? $" … +{m.Steps.Count - 3}" : "");

            items.Add(new LauncherItem(
                m.Name,
                $"{m.Steps.Count}단계  ·  {preview}",
                null, m, Symbol: "\uE768"));
        }

        if (items.Count == 0 && string.IsNullOrEmpty(filter))
        {
            items.Add(new LauncherItem(
                "등록된 매크로 없음",
                "'macro new'로 명령 시퀀스를 추가하세요",
                null, null, Symbol: Symbols.Info));
        }

        items.Add(new LauncherItem(
            "새 매크로 만들기",
            "macro new  ·  앱·URL·폴더·알림을 순서대로 실행",
            null, "__new__", Symbol: "\uE710"));

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

    // ─── 실행 ─────────────────────────────────────────────────────────────
    public Task ExecuteAsync(LauncherItem item, CancellationToken ct)
    {
        if (item.Data is string s)
        {
            if (s == "__new__")
            {
                System.Windows.Application.Current.Dispatcher.Invoke(() =>
                {
                    var win = new Views.MacroEditorWindow(null, _settings);
                    win.Show();
                });
                return Task.CompletedTask;
            }

            if (s.StartsWith("__edit__"))
            {
                var name  = s["__edit__".Length..];
                var entry = _settings.Settings.Macros
                    .FirstOrDefault(x => x.Name.Equals(name, StringComparison.OrdinalIgnoreCase));
                System.Windows.Application.Current.Dispatcher.Invoke(() =>
                {
                    var win = new Views.MacroEditorWindow(entry, _settings);
                    win.Show();
                });
                return Task.CompletedTask;
            }

            if (s.StartsWith("__del__"))
            {
                var name  = s["__del__".Length..];
                var entry = _settings.Settings.Macros
                    .FirstOrDefault(x => x.Name.Equals(name, StringComparison.OrdinalIgnoreCase));
                if (entry != null)
                {
                    _settings.Settings.Macros.Remove(entry);
                    _settings.Save();
                    NotificationService.Notify("AX Copilot", $"매크로 '{name}' 삭제됨");
                }
                return Task.CompletedTask;
            }
        }

        // 매크로 항목 Enter → 실행
        if (item.Data is MacroEntry macro)
        {
            _ = RunMacroAsync(macro, ct);
        }

        return Task.CompletedTask;
    }

    // ─── 매크로 재생 ──────────────────────────────────────────────────────
    internal static async Task RunMacroAsync(MacroEntry macro, CancellationToken ct)
    {
        int executed = 0;
        foreach (var step in macro.Steps)
        {
            if (ct.IsCancellationRequested) break;

            if (step.DelayMs > 0)
                await Task.Delay(step.DelayMs, ct).ConfigureAwait(false);

            try
            {
                switch (step.Type.ToLowerInvariant())
                {
                    case "app":
                        if (!string.IsNullOrWhiteSpace(step.Target))
                            Process.Start(new ProcessStartInfo
                            {
                                FileName        = step.Target,
                                Arguments       = step.Args ?? "",
                                UseShellExecute = true
                            });
                        break;

                    case "url":
                    case "folder":
                        if (!string.IsNullOrWhiteSpace(step.Target))
                            Process.Start(new ProcessStartInfo(step.Target)
                                { UseShellExecute = true });
                        break;

                    case "notification":
                        var msg = string.IsNullOrWhiteSpace(step.Label) ? step.Target : step.Label;
                        NotificationService.Notify($"[매크로] {macro.Name}", msg);
                        break;

                    case "cmd":
                        if (!string.IsNullOrWhiteSpace(step.Target))
                            Process.Start(new ProcessStartInfo("powershell.exe",
                                $"-NoProfile -ExecutionPolicy Bypass -Command \"{step.Target}\"")
                                { UseShellExecute = false, CreateNoWindow = true });
                        break;
                }
                executed++;
            }
            catch (Exception ex)
            {
                LogService.Warn($"매크로 단계 실행 실패 '{step.Label}': {ex.Message}");
            }
        }

        NotificationService.Notify("매크로 완료",
            $"[{macro.Name}] {executed}/{macro.Steps.Count}단계 실행됨");
    }
}
