using System;
using System.Collections.Generic;
using System.Globalization;
using System.Threading;
using System.Threading.Tasks;
using System.Windows;
using AxCopilot.SDK;

namespace AxCopilot.Handlers;

public class CalculatorHandler : IActionHandler
{
	public string? Prefix => "=";

	public PluginMetadata Metadata => new PluginMetadata("Calculator", "수식 계산기 — = 뒤에 수식 입력", "1.0", "AX");

	public async Task<IEnumerable<LauncherItem>> GetItemsAsync(string query, CancellationToken ct)
	{
		if (string.IsNullOrWhiteSpace(query))
		{
			return new _003C_003Ez__ReadOnlySingleElementList<LauncherItem>(new LauncherItem("수식을 입력하세요", "예: 1+2*3 · sqrt(16) · 100km in miles · 100 USD to KRW", null, null, null, "\ue8ef"));
		}
		string trimmed = query.Trim();
		if (CurrencyConverter.IsCurrencyQuery(trimmed))
		{
			return await CurrencyConverter.ConvertAsync(trimmed, ct);
		}
		if (UnitConverter.TryConvert(trimmed, out string convertResult))
		{
			return new _003C_003Ez__ReadOnlySingleElementList<LauncherItem>(new LauncherItem(convertResult, trimmed + "  ·  Enter로 클립보드에 복사", null, convertResult, null, "\ue8ef"));
		}
		try
		{
			double value = MathEvaluator.Evaluate(trimmed);
			string result = FormatResult(value);
			return new _003C_003Ez__ReadOnlySingleElementList<LauncherItem>(new LauncherItem(result, trimmed + " = " + result + "  ·  Enter로 클립보드에 복사", null, result, null, "\ue8ef"));
		}
		catch (Exception ex)
		{
			return new _003C_003Ez__ReadOnlySingleElementList<LauncherItem>(new LauncherItem("계산할 수 없습니다", ex.Message, null, null, null, "\uea39"));
		}
	}

	public Task ExecuteAsync(LauncherItem item, CancellationToken ct)
	{
		if (item.Data is string text)
		{
			try
			{
				Clipboard.SetText(text);
			}
			catch
			{
			}
		}
		return Task.CompletedTask;
	}

	private static string FormatResult(double value)
	{
		if (double.IsNaN(value))
		{
			return "NaN";
		}
		if (double.IsPositiveInfinity(value))
		{
			return "∞";
		}
		if (double.IsNegativeInfinity(value))
		{
			return "-∞";
		}
		if (value == Math.Floor(value) && Math.Abs(value) < 1000000000000000.0)
		{
			return ((long)value).ToString();
		}
		return value.ToString("G10", CultureInfo.InvariantCulture);
	}
}
