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

namespace AxCopilot.Handlers;

public class WebSearchHandler : IActionHandler
{
	private readonly SettingsService _settings;

	private static readonly string _iconDir = Path.Combine(Path.GetDirectoryName(Assembly.GetExecutingAssembly().Location) ?? ".", "Assets", "SearchEngines");

	private static readonly Dictionary<string, (string Name, string UrlTemplate, string Icon)> _engines = new Dictionary<string, (string, string, string)>
	{
		["g"] = ("Google", "https://www.google.com/search?q={0}", "google"),
		["n"] = ("Naver", "https://search.naver.com/search.naver?query={0}", "naver"),
		["y"] = ("YouTube", "https://www.youtube.com/results?search_query={0}", "youtube"),
		["gh"] = ("GitHub", "https://github.com/search?q={0}", "github"),
		["d"] = ("DuckDuckGo", "https://duckduckgo.com/?q={0}", "duckduckgo"),
		["w"] = ("Wikipedia", "https://ko.wikipedia.org/w/index.php?search={0}", "wikipedia"),
		["nm"] = ("Naver Map", "https://map.naver.com/p/search/{0}", "navermap"),
		["nw"] = ("나무위키", "https://namu.wiki/Special:Search?query={0}", "namuwiki"),
		["ni"] = ("Naver 이미지", "https://search.naver.com/search.naver?where=image&query={0}", "naver"),
		["gi"] = ("Google 이미지", "https://www.google.com/search?tbm=isch&q={0}", "google")
	};

	private const string SecurityWarn = "⚠ 검색어가 외부로 전송됩니다 — 기밀 데이터 입력 금지";

	public string? Prefix => "?";

	public PluginMetadata Metadata => new PluginMetadata("WebSearch", "웹 검색 — ? 뒤에 검색어 또는 URL 입력", "1.0", "AX");

	private string DefaultEngineKey => _settings.Settings.Launcher.WebSearchEngine ?? "g";

	private (string Name, string UrlTemplate, string Icon) DefaultEngine
	{
		get
		{
			(string, string, string) value;
			return _engines.TryGetValue(DefaultEngineKey, out value) ? value : _engines["g"];
		}
	}

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

	private static string? GetIconPath(string engineKey)
	{
		if (!_engines.TryGetValue(engineKey, out (string, string, string) value))
		{
			return null;
		}
		string text = Path.Combine(_iconDir, value.Item3 + ".png");
		return File.Exists(text) ? text : null;
	}

	public Task<IEnumerable<LauncherItem>> GetItemsAsync(string query, CancellationToken ct)
	{
		if (string.IsNullOrWhiteSpace(query))
		{
			string iconPath = GetIconPath(DefaultEngineKey);
			return Task.FromResult((IEnumerable<LauncherItem>)new _003C_003Ez__ReadOnlySingleElementList<LauncherItem>(new LauncherItem("검색어를 입력하세요", "예: ? 오늘 날씨  ·  ?g python  ·  ?y 음악  ·  ?n 뉴스  |  ⚠ 검색어가 외부로 전송됩니다 — 기밀 데이터 입력 금지", iconPath, null, null, "\ue774")));
		}
		List<LauncherItem> list = new List<LauncherItem>();
		string text = query.Trim();
		if (IsUrl(text))
		{
			string text2 = (text.StartsWith("http", StringComparison.OrdinalIgnoreCase) ? text : ("https://" + text));
			string faviconPathForUrl = GetFaviconPathForUrl(text2);
			list.Add(new LauncherItem("열기: " + text, text2 + "  |  ⚠ 검색어가 외부로 전송됩니다 — 기밀 데이터 입력 금지", faviconPathForUrl, text2, null, "\ue774"));
			return Task.FromResult((IEnumerable<LauncherItem>)list);
		}
		string[] array = text.Split(' ', 2);
		string text3 = array[0].ToLowerInvariant();
		if (array.Length == 2 && _engines.TryGetValue(text3, out (string, string, string) value))
		{
			string text4 = array[1].Trim();
			if (!string.IsNullOrWhiteSpace(text4))
			{
				string data = string.Format(value.Item2, Uri.EscapeDataString(text4));
				list.Add(new LauncherItem(value.Item1 + "에서 '" + text4 + "' 검색", "⚠ 검색어가 외부로 전송됩니다 — 기밀 데이터 입력 금지", GetIconPath(text3), data, null, "\ue774"));
			}
		}
		string defaultEngineKey = DefaultEngineKey;
		(string, string, string) defaultEngine = DefaultEngine;
		string data2 = string.Format(defaultEngine.Item2, Uri.EscapeDataString(text));
		list.Add(new LauncherItem(defaultEngine.Item1 + "에서 '" + text + "' 검색", "⚠ 검색어가 외부로 전송됩니다 — 기밀 데이터 입력 금지", GetIconPath(defaultEngineKey), data2, null, "\ue774"));
		if (text.Length <= 2)
		{
			foreach (var (text6, tuple2) in _engines)
			{
				list.Add(new LauncherItem("?" + text6 + " — " + tuple2.Item1, $"예: ?{text6} {text}  |  {"⚠ 검색어가 외부로 전송됩니다 — 기밀 데이터 입력 금지"}", GetIconPath(text6), null, null, "\ue774"));
			}
		}
		return Task.FromResult((IEnumerable<LauncherItem>)list);
	}

	public Task ExecuteAsync(LauncherItem item, CancellationToken ct)
	{
		if (item.Data is string text && !string.IsNullOrWhiteSpace(text))
		{
			try
			{
				Process.Start(new ProcessStartInfo(text)
				{
					UseShellExecute = true
				});
			}
			catch (Exception ex)
			{
				LogService.Warn("웹 검색 열기 실패: " + ex.Message);
			}
		}
		return Task.CompletedTask;
	}

	private static bool IsUrl(string input)
	{
		if (input.StartsWith("http://", StringComparison.OrdinalIgnoreCase) || input.StartsWith("https://", StringComparison.OrdinalIgnoreCase))
		{
			return true;
		}
		if (!input.Contains(' ') && input.Contains('.') && input.Length > 3)
		{
			string text = input.Split('/')[0];
			string[] array = text.Split('.');
			return array.Length >= 2 && array[^1].Length >= 2 && array[^1].Length <= 6 && array[^1].All(char.IsLetter);
		}
		return false;
	}

	private static string? GetFaviconPathForUrl(string url)
	{
		try
		{
			if (!url.StartsWith("http", StringComparison.OrdinalIgnoreCase))
			{
				url = "https://" + url;
			}
			string text = new Uri(url).Host.ToLowerInvariant();
			string text2 = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.ApplicationData), "AxCopilot", "favicons", text + ".png");
			if (File.Exists(text2))
			{
				return text2;
			}
			FaviconService.GetFavicon(url);
			return null;
		}
		catch
		{
			return null;
		}
	}
}
