using System.Reflection;

namespace Hua.Todo.Maui.Platforms.Windows;

internal static class WebView2RuntimeDetector
{
	/// <summary>
	/// 判断当前 Windows 系统是否可用 WebView2 Runtime。
	/// 优先通过已知的 Evergreen 安装目录探测（避免因托管程序集缺失/裁剪导致误判），
	/// 其次再尝试通过 WebView2 SDK 的 <c>CoreWebView2Environment.GetAvailableBrowserVersionString</c> 获取版本。
	/// </summary>
	/// <param name="version">检测到的运行时版本（若可用）。</param>
	/// <returns>若系统存在可用的 WebView2 Runtime，则返回 <c>true</c>；否则返回 <c>false</c>。</returns>
	internal static bool IsRuntimeInstalled(out string? version)
	{
		version = null;

		try
		{
			version = TryGetEvergreenVersionFromKnownLocations();
			if (!string.IsNullOrWhiteSpace(version))
			{
				return true;
			}

			var type = Type.GetType("Microsoft.Web.WebView2.Core.CoreWebView2Environment, Microsoft.Web.WebView2.Core");
			if (type == null)
			{
				return false;
			}

			version = TryInvokeVersionGetter(type);
			return !string.IsNullOrWhiteSpace(version);
		}
		catch
		{
			return false;
		}
	}

	private static string? TryGetEvergreenVersionFromKnownLocations()
	{
		var candidates = new[]
		{
			Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFilesX86), "Microsoft", "EdgeWebView", "Application"),
			Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ProgramFiles), "Microsoft", "EdgeWebView", "Application"),
			Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "Microsoft", "EdgeWebView", "Application"),
		};

		Version? best = null;

		foreach (var baseDir in candidates)
		{
			if (string.IsNullOrWhiteSpace(baseDir) || !Directory.Exists(baseDir))
			{
				continue;
			}

			foreach (var dir in Directory.EnumerateDirectories(baseDir))
			{
				var name = Path.GetFileName(dir);
				if (!Version.TryParse(name, out var v))
				{
					continue;
				}

				if (!File.Exists(Path.Combine(dir, "msedgewebview2.exe")))
				{
					continue;
				}

				if (best == null || v > best)
				{
					best = v;
				}
			}
		}

		return best?.ToString();
	}

	private static string? TryInvokeVersionGetter(Type environmentType)
	{
		var noArg = environmentType.GetMethod("GetAvailableBrowserVersionString", BindingFlags.Public | BindingFlags.Static, Type.DefaultBinder, Type.EmptyTypes, null);
		if (noArg != null)
		{
			return noArg.Invoke(null, null) as string;
		}

		var oneArg = environmentType.GetMethod("GetAvailableBrowserVersionString", BindingFlags.Public | BindingFlags.Static, Type.DefaultBinder, new[] { typeof(string) }, null);
		if (oneArg != null)
		{
			return oneArg.Invoke(null, new object?[] { null }) as string;
		}

		return null;
	}
}

