using System.Diagnostics;
using System.ServiceProcess;
using System.Windows;
using AxCopilot.SDK;
using AxCopilot.Services;
using AxCopilot.Themes;

namespace AxCopilot.Handlers;

/// <summary>
/// Windows 서비스 관리 핸들러. "svc" 프리픽스로 사용합니다.
/// 서비스 검색, 상태 조회, 시작/중지/재시작.
/// 특수 명령: svc restart clipboard → 클립보드 히스토리 서비스 강제 재시작
/// 예: svc              → 실행 중 서비스 목록 (상위 20개)
///     svc spooler      → "spooler" 검색
///     svc start [이름] → 서비스 시작
///     svc stop [이름]  → 서비스 중지
///     svc restart clipboard → AX 클립보드 히스토리 서비스 재시작
/// </summary>
public class ServiceHandler : IActionHandler
{
    private readonly ClipboardHistoryService? _clipboardService;

    public ServiceHandler(ClipboardHistoryService? clipboardService = null)
    {
        _clipboardService = clipboardService;
    }

    public string? Prefix => "svc";

    public PluginMetadata Metadata => new(
        "Service",
        "Windows 서비스 관리 — svc",
        "1.0",
        "AX");

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

        // 특수: 클립보드 서비스 재시작
        if (q.Equals("restart clipboard", StringComparison.OrdinalIgnoreCase) ||
            q.Equals("클립보드 재시작", StringComparison.OrdinalIgnoreCase))
        {
            items.Add(new LauncherItem(
                "AX 클립보드 히스토리 서비스 재시작",
                "클립보드 감지가 작동하지 않을 때 사용  ·  Enter로 실행",
                null, "__RESTART_CLIPBOARD__",
                Symbol: Symbols.Restart));
            return Task.FromResult<IEnumerable<LauncherItem>>(items);
        }

        // start/stop/restart 명령
        if (q.StartsWith("start ", StringComparison.OrdinalIgnoreCase) ||
            q.StartsWith("stop ", StringComparison.OrdinalIgnoreCase) ||
            q.StartsWith("restart ", StringComparison.OrdinalIgnoreCase))
        {
            var parts = q.Split(' ', 2, StringSplitOptions.TrimEntries);
            var action = parts[0].ToLowerInvariant();
            var svcName = parts.Length > 1 ? parts[1] : "";

            if (!string.IsNullOrWhiteSpace(svcName))
            {
                try
                {
                    var svc = ServiceController.GetServices()
                        .FirstOrDefault(s =>
                            s.ServiceName.Contains(svcName, StringComparison.OrdinalIgnoreCase) ||
                            s.DisplayName.Contains(svcName, StringComparison.OrdinalIgnoreCase));

                    if (svc != null)
                    {
                        var actionLabel = action switch
                        {
                            "start"   => "시작",
                            "stop"    => "중지",
                            "restart" => "재시작",
                            _ => action
                        };
                        items.Add(new LauncherItem(
                            $"[{actionLabel}] {svc.DisplayName}",
                            $"서비스명: {svc.ServiceName}  ·  현재 상태: {StatusText(svc.Status)}  ·  Enter로 실행",
                            null, ($"__{action.ToUpperInvariant()}__", svc.ServiceName),
                            Symbol: action == "stop" ? Symbols.Error : Symbols.Restart));
                    }
                    else
                    {
                        items.Add(new LauncherItem(
                            $"'{svcName}' 서비스를 찾을 수 없습니다",
                            "서비스 이름 또는 표시 이름으로 검색",
                            null, null, Symbol: Symbols.Warning));
                    }
                }
                catch (Exception ex)
                {
                    items.Add(new LauncherItem("서비스 조회 실패", ex.Message, null, null, Symbol: Symbols.Error));
                }

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

        // 서비스 검색/목록
        try
        {
            var services = ServiceController.GetServices();
            var filtered = string.IsNullOrWhiteSpace(q)
                ? services.Where(s => s.Status == ServiceControllerStatus.Running)
                    .OrderBy(s => s.DisplayName).Take(20)
                : services.Where(s =>
                        s.ServiceName.Contains(q, StringComparison.OrdinalIgnoreCase) ||
                        s.DisplayName.Contains(q, StringComparison.OrdinalIgnoreCase))
                    .OrderBy(s => s.DisplayName).Take(20);

            // 클립보드 재시작 항목 항상 상단에 표시
            items.Add(new LauncherItem(
                "AX 클립보드 히스토리 서비스 재시작",
                "svc restart clipboard  ·  클립보드 감지 문제 시 사용",
                null, "__RESTART_CLIPBOARD__",
                Symbol: Symbols.Restart));

            foreach (var svc in filtered)
            {
                var status = StatusText(svc.Status);
                var symbol = svc.Status == ServiceControllerStatus.Running
                    ? "\uE73E" // 체크마크
                    : "\uE711"; // X

                items.Add(new LauncherItem(
                    $"[{status}] {svc.DisplayName}",
                    $"{svc.ServiceName}  ·  svc start/stop/restart {svc.ServiceName}",
                    null, svc.ServiceName,
                    Symbol: symbol));
            }
        }
        catch (Exception ex)
        {
            items.Add(new LauncherItem("서비스 조회 실패", ex.Message, null, null, Symbol: Symbols.Error));
        }

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

    public Task ExecuteAsync(LauncherItem item, CancellationToken ct)
    {
        // 클립보드 서비스 재시작
        if (item.Data is string s && s == "__RESTART_CLIPBOARD__")
        {
            RestartClipboardService();
            return Task.CompletedTask;
        }

        // Windows 서비스 제어
        if (item.Data is ValueTuple<string, string> cmd)
        {
            var (action, svcName) = cmd;
            return ExecuteServiceAction(action, svcName);
        }

        // 서비스 이름 클립보드 복사
        if (item.Data is string name)
        {
            try { Application.Current?.Dispatcher.Invoke(() => Clipboard.SetText(name)); }
            catch (Exception) { }
        }

        return Task.CompletedTask;
    }

    private void RestartClipboardService()
    {
        try
        {
            if (_clipboardService == null)
            {
                NotificationService.Notify("AX Copilot", "클립보드 서비스 참조를 찾을 수 없습니다.");
                return;
            }

            // Dispose 후 재초기화
            _clipboardService.Dispose();

            // 약간의 딜레이 후 재초기화
            Application.Current?.Dispatcher.BeginInvoke(() =>
            {
                try
                {
                    _clipboardService.Reinitialize();
                    NotificationService.Notify("AX Copilot", "클립보드 히스토리 서비스가 재시작되었습니다.");
                    LogService.Info("클립보드 히스토리 서비스 강제 재시작 완료");
                }
                catch (Exception ex)
                {
                    NotificationService.Notify("AX Copilot", $"클립보드 재시작 실패: {ex.Message}");
                    LogService.Error($"클립보드 재시작 실패: {ex.Message}");
                }
            }, System.Windows.Threading.DispatcherPriority.Background);
        }
        catch (Exception ex)
        {
            NotificationService.Notify("AX Copilot", $"클립보드 재시작 실패: {ex.Message}");
        }
    }

    private static async Task ExecuteServiceAction(string action, string svcName)
    {
        try
        {
            // sc.exe를 사용하여 관리자 권한으로 실행
            var verb = action switch
            {
                "__START__"   => "start",
                "__STOP__"    => "stop",
                "__RESTART__" => "stop", // restart는 stop + start
                _ => null
            };

            if (verb == null) return;

            var psi = new ProcessStartInfo("sc.exe", $"{verb} \"{svcName}\"")
            {
                Verb = "runas",
                UseShellExecute = true,
                CreateNoWindow = true,
                WindowStyle = ProcessWindowStyle.Hidden
            };

            var proc = Process.Start(psi);
            proc?.WaitForExit(5000);

            if (action == "__RESTART__")
            {
                await Task.Delay(1000);
                var startPsi = new ProcessStartInfo("sc.exe", $"start \"{svcName}\"")
                {
                    Verb = "runas",
                    UseShellExecute = true,
                    CreateNoWindow = true,
                    WindowStyle = ProcessWindowStyle.Hidden
                };
                Process.Start(startPsi)?.WaitForExit(5000);
            }

            var label = action switch
            {
                "__START__"   => "시작",
                "__STOP__"    => "중지",
                "__RESTART__" => "재시작",
                _ => action
            };
            NotificationService.Notify("서비스 관리", $"{svcName} {label} 요청 완료");
        }
        catch (Exception ex)
        {
            NotificationService.Notify("AX Copilot", $"서비스 제어 실패: {ex.Message}");
        }
    }

    private static string StatusText(ServiceControllerStatus status) => status switch
    {
        ServiceControllerStatus.Running         => "실행 중",
        ServiceControllerStatus.Stopped         => "중지됨",
        ServiceControllerStatus.StartPending    => "시작 중",
        ServiceControllerStatus.StopPending     => "중지 중",
        ServiceControllerStatus.Paused          => "일시 중지",
        ServiceControllerStatus.ContinuePending => "재개 중",
        ServiceControllerStatus.PausePending    => "일시 중지 중",
        _ => status.ToString()
    };
}
