using System;
using System.Collections.Generic;
using System.IO;
using System.Runtime.InteropServices;
using System.Text;
using System.Text.Json;
using System.Text.RegularExpressions;
using System.Threading;
using System.Threading.Tasks;

namespace AxCopilot.Services.Agent;

public class HtmlSkill : IAgentTool
{
	public string Name => "html_create";

	public string Description => "Create a styled HTML (.html) document with rich formatting. Supports: table of contents (toc), cover page, callouts (.callout-info/warning/tip/danger), badges (.badge-blue/green/red/yellow/purple), CSS bar charts (.chart-bar), progress bars (.progress), timelines (.timeline), grid layouts (.grid-2/3/4), and auto section numbering. Available moods: modern, professional, creative, minimal, elegant, dark, colorful, corporate, magazine, dashboard.";

	public ToolParameterSchema Parameters
	{
		get
		{
			ToolParameterSchema obj = new ToolParameterSchema
			{
				Properties = new Dictionary<string, ToolProperty>
				{
					["path"] = new ToolProperty
					{
						Type = "string",
						Description = "Output file path (.html). Relative to work folder."
					},
					["title"] = new ToolProperty
					{
						Type = "string",
						Description = "Document title (shown in browser tab and header)"
					},
					["body"] = new ToolProperty
					{
						Type = "string",
						Description = "HTML body content. Use semantic tags: h2/h3 for sections, div.callout-info/warning/tip/danger for callouts, span.badge-blue/green/red for badges, div.chart-bar>div.bar-item for charts, div.grid-2/3/4 for grid layouts, div.timeline>div.timeline-item for timelines, div.progress for progress bars."
					},
					["mood"] = new ToolProperty
					{
						Type = "string",
						Description = "Design template mood: modern, professional, creative, minimal, elegant, dark, colorful, corporate, magazine, dashboard. Default: modern"
					},
					["style"] = new ToolProperty
					{
						Type = "string",
						Description = "Optional additional CSS. Appended after mood+shared CSS."
					},
					["toc"] = new ToolProperty
					{
						Type = "boolean",
						Description = "Auto-generate table of contents from h2/h3 headings. Default: false"
					},
					["numbered"] = new ToolProperty
					{
						Type = "boolean",
						Description = "Auto-number h2/h3 sections (1., 1-1., etc). Default: false"
					},
					["cover"] = new ToolProperty
					{
						Type = "object",
						Description = "Cover page config: {\"title\": \"...\", \"subtitle\": \"...\", \"author\": \"...\", \"date\": \"...\", \"gradient\": \"#hex1,#hex2\"}. Omit to skip cover page."
					}
				}
			};
			int num = 3;
			List<string> list = new List<string>(num);
			CollectionsMarshal.SetCount(list, num);
			Span<string> span = CollectionsMarshal.AsSpan(list);
			span[0] = "path";
			span[1] = "title";
			span[2] = "body";
			obj.Required = list;
			return obj;
		}
	}

	public async Task<ToolResult> ExecuteAsync(JsonElement args, AgentContext context, CancellationToken ct)
	{
		string path = args.GetProperty("path").GetString() ?? "";
		string title = args.GetProperty("title").GetString() ?? "Report";
		string body = args.GetProperty("body").GetString() ?? "";
		JsonElement s;
		string customStyle = (args.TryGetProperty("style", out s) ? s.GetString() : null);
		JsonElement m;
		string mood = (args.TryGetProperty("mood", out m) ? (m.GetString() ?? "modern") : "modern");
		JsonElement tocVal;
		bool useToc = args.TryGetProperty("toc", out tocVal) && tocVal.GetBoolean();
		JsonElement numVal;
		bool useNumbered = args.TryGetProperty("numbered", out numVal) && numVal.GetBoolean();
		JsonElement coverVal;
		bool hasCover = args.TryGetProperty("cover", out coverVal) && coverVal.ValueKind == JsonValueKind.Object;
		string fullPath = FileReadTool.ResolvePath(path, context.WorkFolder);
		if (context.ActiveTab == "Cowork")
		{
			fullPath = AgentContext.EnsureTimestampedPath(fullPath);
		}
		if (!fullPath.EndsWith(".html", StringComparison.OrdinalIgnoreCase) && !fullPath.EndsWith(".htm", StringComparison.OrdinalIgnoreCase))
		{
			fullPath += ".html";
		}
		if (!context.IsPathAllowed(fullPath))
		{
			return ToolResult.Fail("경로 접근 차단: " + fullPath);
		}
		if (!(await context.CheckWritePermissionAsync(Name, fullPath)))
		{
			return ToolResult.Fail("쓰기 권한 거부: " + fullPath);
		}
		try
		{
			string dir = Path.GetDirectoryName(fullPath);
			if (!string.IsNullOrEmpty(dir))
			{
				Directory.CreateDirectory(dir);
			}
			string style = TemplateService.GetCss(mood);
			if (!string.IsNullOrEmpty(customStyle))
			{
				style = style + "\n" + customStyle;
			}
			TemplateMood moodInfo = TemplateService.GetMood(mood);
			string moodLabel = ((moodInfo != null) ? (" · " + moodInfo.Icon + " " + moodInfo.Label) : "");
			if (useNumbered)
			{
				body = AddNumberedClass(body);
			}
			body = EnsureHeadingIds(body);
			string tocHtml = (useToc ? GenerateToc(body) : "");
			string coverHtml = (hasCover ? GenerateCover(coverVal, title) : "");
			StringBuilder sb = new StringBuilder();
			sb.AppendLine("<!DOCTYPE html>");
			sb.AppendLine("<html lang=\"ko\">");
			sb.AppendLine("<head>");
			sb.AppendLine("<meta charset=\"UTF-8\">");
			sb.AppendLine("<meta name=\"viewport\" content=\"width=device-width, initial-scale=1.0\">");
			StringBuilder stringBuilder = sb;
			StringBuilder stringBuilder2 = stringBuilder;
			StringBuilder.AppendInterpolatedStringHandler handler = new StringBuilder.AppendInterpolatedStringHandler(15, 1, stringBuilder);
			handler.AppendLiteral("<title>");
			handler.AppendFormatted(Escape(title));
			handler.AppendLiteral("</title>");
			stringBuilder2.AppendLine(ref handler);
			stringBuilder = sb;
			StringBuilder stringBuilder3 = stringBuilder;
			handler = new StringBuilder.AppendInterpolatedStringHandler(15, 1, stringBuilder);
			handler.AppendLiteral("<style>");
			handler.AppendFormatted(style);
			handler.AppendLiteral("</style>");
			stringBuilder3.AppendLine(ref handler);
			sb.AppendLine("</head>");
			sb.AppendLine("<body>");
			sb.AppendLine("<div class=\"container\">");
			if (!string.IsNullOrEmpty(coverHtml))
			{
				sb.AppendLine(coverHtml);
			}
			else
			{
				stringBuilder = sb;
				StringBuilder stringBuilder4 = stringBuilder;
				handler = new StringBuilder.AppendInterpolatedStringHandler(9, 1, stringBuilder);
				handler.AppendLiteral("<h1>");
				handler.AppendFormatted(Escape(title));
				handler.AppendLiteral("</h1>");
				stringBuilder4.AppendLine(ref handler);
				stringBuilder = sb;
				StringBuilder stringBuilder5 = stringBuilder;
				handler = new StringBuilder.AppendInterpolatedStringHandler(41, 2, stringBuilder);
				handler.AppendLiteral("<div class=\"meta\">생성: ");
				handler.AppendFormatted(DateTime.Now, "yyyy-MM-dd HH:mm");
				handler.AppendLiteral(" | AX Copilot");
				handler.AppendFormatted(moodLabel);
				handler.AppendLiteral("</div>");
				stringBuilder5.AppendLine(ref handler);
			}
			if (!string.IsNullOrEmpty(tocHtml))
			{
				sb.AppendLine(tocHtml);
			}
			sb.AppendLine(body);
			sb.AppendLine("</div>");
			sb.AppendLine("</body>");
			sb.AppendLine("</html>");
			await File.WriteAllTextAsync(fullPath, sb.ToString(), Encoding.UTF8, ct);
			List<string> features = new List<string>();
			if (useToc)
			{
				features.Add("목차");
			}
			if (useNumbered)
			{
				features.Add("섹션번호");
			}
			if (hasCover)
			{
				features.Add("커버페이지");
			}
			string featureStr = ((features.Count > 0) ? (" [" + string.Join(", ", features) + "]") : "");
			return ToolResult.Ok($"HTML 문서 생성 완료: {fullPath} (디자인: {mood}{featureStr})", fullPath);
		}
		catch (Exception ex)
		{
			return ToolResult.Fail("HTML 생성 실패: " + ex.Message);
		}
	}

	private static string EnsureHeadingIds(string html)
	{
		int counter = 0;
		return Regex.Replace(html, "<(h[23])(\\s[^>]*)?>", delegate(Match match)
		{
			string value = match.Groups[1].Value;
			string value2 = match.Groups[2].Value;
			counter++;
			return (!value2.Contains("id=", StringComparison.OrdinalIgnoreCase)) ? $"<{value}{value2} id=\"section-{counter}\">" : match.Value;
		});
	}

	private static string AddNumberedClass(string html)
	{
		return Regex.Replace(html, "<(h[23])(\\s[^>]*)?>", delegate(Match match)
		{
			string value = match.Groups[1].Value;
			string value2 = match.Groups[2].Value;
			if (value2.Contains("numbered", StringComparison.OrdinalIgnoreCase))
			{
				return match.Value;
			}
			return Regex.IsMatch(value2, "class\\s*=\\s*\"", RegexOptions.IgnoreCase) ? Regex.Replace(match.Value, "class\\s*=\\s*\"", "class=\"numbered ") : ("<" + value + value2 + " class=\"numbered\">");
		});
	}

	private static string GenerateToc(string html)
	{
		MatchCollection matchCollection = Regex.Matches(html, "<(h[23])[^>]*id=\"([^\"]+)\"[^>]*>(.*?)</\\1>", RegexOptions.IgnoreCase | RegexOptions.Singleline);
		if (matchCollection.Count == 0)
		{
			return "";
		}
		StringBuilder stringBuilder = new StringBuilder();
		stringBuilder.AppendLine("<nav class=\"toc\">");
		stringBuilder.AppendLine("<h2>\ud83d\udccb 목차</h2>");
		stringBuilder.AppendLine("<ul>");
		foreach (Match item in matchCollection)
		{
			string text = item.Groups[1].Value.ToLower();
			string value = item.Groups[2].Value;
			string value2 = Regex.Replace(item.Groups[3].Value, "<[^>]+>", "").Trim();
			string value3 = ((text == "h3") ? " class=\"toc-h3\"" : "");
			StringBuilder stringBuilder2 = stringBuilder;
			StringBuilder.AppendInterpolatedStringHandler handler = new StringBuilder.AppendInterpolatedStringHandler(25, 3, stringBuilder2);
			handler.AppendLiteral("<li");
			handler.AppendFormatted(value3);
			handler.AppendLiteral("><a href=\"#");
			handler.AppendFormatted(value);
			handler.AppendLiteral("\">");
			handler.AppendFormatted(value2);
			handler.AppendLiteral("</a></li>");
			stringBuilder2.AppendLine(ref handler);
		}
		stringBuilder.AppendLine("</ul>");
		stringBuilder.AppendLine("</nav>");
		return stringBuilder.ToString();
	}

	private static string GenerateCover(JsonElement cover, string fallbackTitle)
	{
		JsonElement value;
		string s = (cover.TryGetProperty("title", out value) ? (value.GetString() ?? fallbackTitle) : fallbackTitle);
		JsonElement value2;
		string text = (cover.TryGetProperty("subtitle", out value2) ? (value2.GetString() ?? "") : "");
		JsonElement value3;
		string text2 = (cover.TryGetProperty("author", out value3) ? (value3.GetString() ?? "") : "");
		JsonElement value4;
		string item = (cover.TryGetProperty("date", out value4) ? (value4.GetString() ?? DateTime.Now.ToString("yyyy-MM-dd")) : DateTime.Now.ToString("yyyy-MM-dd"));
		JsonElement value5;
		string text3 = (cover.TryGetProperty("gradient", out value5) ? value5.GetString() : null);
		string value6 = "";
		if (!string.IsNullOrEmpty(text3) && text3.Contains(','))
		{
			string[] array = text3.Split(',');
			value6 = $" style=\"background: linear-gradient(135deg, {array[0].Trim()} 0%, {array[1].Trim()} 100%)\"";
		}
		StringBuilder stringBuilder = new StringBuilder();
		StringBuilder stringBuilder2 = stringBuilder;
		StringBuilder stringBuilder3 = stringBuilder2;
		StringBuilder.AppendInterpolatedStringHandler handler = new StringBuilder.AppendInterpolatedStringHandler(24, 1, stringBuilder2);
		handler.AppendLiteral("<div class=\"cover-page\"");
		handler.AppendFormatted(value6);
		handler.AppendLiteral(">");
		stringBuilder3.AppendLine(ref handler);
		stringBuilder2 = stringBuilder;
		StringBuilder stringBuilder4 = stringBuilder2;
		handler = new StringBuilder.AppendInterpolatedStringHandler(9, 1, stringBuilder2);
		handler.AppendLiteral("<h1>");
		handler.AppendFormatted(Escape(s));
		handler.AppendLiteral("</h1>");
		stringBuilder4.AppendLine(ref handler);
		if (!string.IsNullOrEmpty(text))
		{
			stringBuilder2 = stringBuilder;
			StringBuilder stringBuilder5 = stringBuilder2;
			handler = new StringBuilder.AppendInterpolatedStringHandler(34, 1, stringBuilder2);
			handler.AppendLiteral("<div class=\"cover-subtitle\">");
			handler.AppendFormatted(Escape(text));
			handler.AppendLiteral("</div>");
			stringBuilder5.AppendLine(ref handler);
		}
		stringBuilder.AppendLine("<div class=\"cover-divider\"></div>");
		List<string> list = new List<string>();
		if (!string.IsNullOrEmpty(text2))
		{
			list.Add(text2);
		}
		list.Add(item);
		list.Add("AX Copilot");
		stringBuilder2 = stringBuilder;
		StringBuilder stringBuilder6 = stringBuilder2;
		handler = new StringBuilder.AppendInterpolatedStringHandler(30, 1, stringBuilder2);
		handler.AppendLiteral("<div class=\"cover-meta\">");
		handler.AppendFormatted(Escape(string.Join(" · ", list)));
		handler.AppendLiteral("</div>");
		stringBuilder6.AppendLine(ref handler);
		stringBuilder.AppendLine("</div>");
		return stringBuilder.ToString();
	}

	private static string Escape(string s)
	{
		return s.Replace("&", "&amp;").Replace("<", "&lt;").Replace(">", "&gt;");
	}
}
