using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using AxCopilot.SDK;
using AxCopilot.Services;

namespace AxCopilot.Handlers;

public class ProcessHandler : IActionHandler
{
	private record ProcessKillData(string Name, List<int> Pids);

	private static readonly HashSet<string> ProtectedProcesses = new HashSet<string>(StringComparer.OrdinalIgnoreCase)
	{
		"system", "smss", "csrss", "wininit", "winlogon", "services", "lsass", "svchost", "explorer", "dwm",
		"fontdrvhost", "spoolsv", "registry"
	};

	public string? Prefix => "kill ";

	public PluginMetadata Metadata => new PluginMetadata("ProcessKiller", "프로세스 종료 — kill 뒤에 프로세스명 입력", "1.0", "AX");

	public Task<IEnumerable<LauncherItem>> GetItemsAsync(string query, CancellationToken ct)
	{
		if (string.IsNullOrWhiteSpace(query))
		{
			return Task.FromResult((IEnumerable<LauncherItem>)new _003C_003Ez__ReadOnlySingleElementList<LauncherItem>(new LauncherItem("종료할 프로세스명을 입력하세요", "예: kill chrome  ·  kill notepad  ·  kill explorer", null, null, null, "\ue7e8")));
		}
		string q = query.Trim().ToLowerInvariant();
		try
		{
			List<Process> list = (from p in Process.GetProcesses()
				where !ProtectedProcesses.Contains(p.ProcessName) && p.ProcessName.ToLowerInvariant().Contains(q)
				orderby p.ProcessName
				select p).Take(12).ToList();
			if (list.Count == 0)
			{
				return Task.FromResult((IEnumerable<LauncherItem>)new _003C_003Ez__ReadOnlySingleElementList<LauncherItem>(new LauncherItem("'" + query + "' 프로세스를 찾을 수 없습니다", "실행 중인 프로세스가 없거나 이름이 다릅니다", null, null, null, "\ue7ba")));
			}
			List<LauncherItem> result = list.GroupBy<Process, string>((Process p) => p.ProcessName, StringComparer.OrdinalIgnoreCase).Select(delegate(IGrouping<string, Process> g)
			{
				List<int> list2 = g.Select((Process p) => p.Id).ToList();
				long value = g.Sum(delegate(Process p)
				{
					try
					{
						return p.WorkingSet64 / 1024 / 1024;
					}
					catch
					{
						return 0L;
					}
				});
				string title = ((g.Count() > 1) ? $"{g.Key}  ({g.Count()}개 인스턴스)" : g.Key);
				string subtitle = $"PID: {string.Join(", ", list2)}  ·  메모리: {value} MB  ·  Enter로 종료";
				return new LauncherItem(title, subtitle, null, new ProcessKillData(g.Key, list2), null, "\ue7e8");
			}).ToList();
			return Task.FromResult((IEnumerable<LauncherItem>)result);
		}
		catch (Exception ex)
		{
			LogService.Warn("프로세스 목록 조회 실패: " + ex.Message);
			return Task.FromResult((IEnumerable<LauncherItem>)new _003C_003Ez__ReadOnlySingleElementList<LauncherItem>(new LauncherItem("프로세스 목록 조회 실패", ex.Message, null, null, null, "\uea39")));
		}
	}

	public Task ExecuteAsync(LauncherItem item, CancellationToken ct)
	{
		if (!(item.Data is ProcessKillData processKillData))
		{
			return Task.CompletedTask;
		}
		int num = 0;
		int num2 = 0;
		foreach (int pid in processKillData.Pids)
		{
			try
			{
				Process processById = Process.GetProcessById(pid);
				processById.Kill(entireProcessTree: false);
				num++;
			}
			catch
			{
				num2++;
			}
		}
		LogService.Info($"프로세스 종료: {processKillData.Name} — {num}개 성공, {num2}개 실패");
		return Task.CompletedTask;
	}
}
