using System;
using System.Collections.Generic;
using System.Diagnostics;
using System.IO;
using System.Linq;
using System.Text.Json.Nodes;
using System.Threading;
using System.Threading.Tasks;
using AxCopilot.SDK;
using AxCopilot.Services;

namespace AxCopilot.Handlers;

public class BookmarkHandler : IActionHandler
{
	private record BookmarkEntry(string Name, string? Url);

	private List<BookmarkEntry>? _cache;

	private DateTime _cacheTime = DateTime.MinValue;

	private static readonly TimeSpan CacheTtl = TimeSpan.FromMinutes(5.0);

	public string? Prefix => null;

	public PluginMetadata Metadata => new PluginMetadata("Bookmarks", "Chrome / Edge 북마크 검색", "1.0", "AX");

	public Task<IEnumerable<LauncherItem>> GetItemsAsync(string query, CancellationToken ct)
	{
		if (string.IsNullOrWhiteSpace(query))
		{
			return Task.FromResult((IEnumerable<LauncherItem>)Array.Empty<LauncherItem>());
		}
		RefreshCacheIfNeeded();
		if (_cache == null || _cache.Count == 0)
		{
			return Task.FromResult((IEnumerable<LauncherItem>)Array.Empty<LauncherItem>());
		}
		string q = query.Trim().ToLowerInvariant();
		List<LauncherItem> result = (from b in _cache.Where((BookmarkEntry b) => b.Name.ToLowerInvariant().Contains(q) || (b.Url?.ToLowerInvariant().Contains(q) ?? false)).Take(8)
			select new LauncherItem(b.Name, b.Url ?? "", null, b.Url, null, "\ue774")).ToList();
		return Task.FromResult((IEnumerable<LauncherItem>)result);
	}

	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 void RefreshCacheIfNeeded()
	{
		if (_cache != null && DateTime.Now - _cacheTime < CacheTtl)
		{
			return;
		}
		List<BookmarkEntry> list = new List<BookmarkEntry>();
		foreach (string bookmarkFile in GetBookmarkFiles())
		{
			try
			{
				string json = File.ReadAllText(bookmarkFile);
				ParseChromeBookmarks(json, list);
			}
			catch (Exception ex)
			{
				LogService.Warn("북마크 파일 읽기 실패: " + bookmarkFile + " — " + ex.Message);
			}
		}
		_cache = list;
		_cacheTime = DateTime.Now;
		LogService.Info($"북마크 로드 완료: {list.Count}개");
	}

	private static IEnumerable<string> GetBookmarkFiles()
	{
		string localAppData = Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData);
		string[] chromePaths = new string[4]
		{
			Path.Combine(localAppData, "Google", "Chrome", "User Data"),
			Path.Combine(localAppData, "Google", "Chrome Beta", "User Data"),
			Path.Combine(localAppData, "Google", "Chrome Dev", "User Data"),
			Path.Combine(localAppData, "Google", "Chrome SxS", "User Data")
		};
		string[] edgePaths = new string[4]
		{
			Path.Combine(localAppData, "Microsoft", "Edge", "User Data"),
			Path.Combine(localAppData, "Microsoft", "Edge Beta", "User Data"),
			Path.Combine(localAppData, "Microsoft", "Edge Dev", "User Data"),
			Path.Combine(localAppData, "Microsoft", "Edge Canary", "User Data")
		};
		foreach (string profileRoot in chromePaths.Concat(edgePaths))
		{
			if (!Directory.Exists(profileRoot))
			{
				continue;
			}
			string defaultBookmark = Path.Combine(profileRoot, "Default", "Bookmarks");
			if (File.Exists(defaultBookmark))
			{
				yield return defaultBookmark;
			}
			string[] directories = Directory.GetDirectories(profileRoot, "Profile *");
			foreach (string dir in directories)
			{
				string f = Path.Combine(dir, "Bookmarks");
				if (File.Exists(f))
				{
					yield return f;
				}
			}
		}
	}

	private static void ParseChromeBookmarks(string json, List<BookmarkEntry> result)
	{
		JsonNode jsonNode = JsonNode.Parse(json)?["roots"];
		if (jsonNode == null)
		{
			return;
		}
		string[] array = new string[3] { "bookmark_bar", "other", "synced" };
		foreach (string propertyName in array)
		{
			JsonNode jsonNode2 = jsonNode[propertyName];
			if (jsonNode2 != null)
			{
				WalkNode(jsonNode2, result);
			}
		}
	}

	private static void WalkNode(JsonNode node, List<BookmarkEntry> result)
	{
		string text = node["type"]?.GetValue<string>();
		if (text == "url")
		{
			string text2 = node["name"]?.GetValue<string>() ?? "";
			string text3 = node["url"]?.GetValue<string>() ?? "";
			if (!string.IsNullOrWhiteSpace(text2) && !string.IsNullOrWhiteSpace(text3))
			{
				result.Add(new BookmarkEntry(text2, text3));
			}
		}
		else
		{
			if (!(text == "folder"))
			{
				return;
			}
			JsonArray jsonArray = node["children"]?.AsArray();
			if (jsonArray == null)
			{
				return;
			}
			foreach (JsonNode item in jsonArray)
			{
				if (item != null)
				{
					WalkNode(item, result);
				}
			}
		}
	}
}
