using System;
using System.Collections.Generic;
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 RegexTool : IAgentTool
{
	private const int MaxTimeout = 5000;

	public string Name => "regex_tool";

	public string Description => "Regular expression tool. Actions: 'test' — check if text matches a pattern; 'match' — find all matches with groups; 'replace' — replace matches with replacement string; 'split' — split text by pattern; 'extract' — extract named/numbered groups from first match.";

	public ToolParameterSchema Parameters
	{
		get
		{
			ToolParameterSchema toolParameterSchema = new ToolParameterSchema();
			Dictionary<string, ToolProperty> dictionary = new Dictionary<string, ToolProperty>();
			ToolProperty obj = new ToolProperty
			{
				Type = "string",
				Description = "Action to perform"
			};
			int num = 5;
			List<string> list = new List<string>(num);
			CollectionsMarshal.SetCount(list, num);
			Span<string> span = CollectionsMarshal.AsSpan(list);
			span[0] = "test";
			span[1] = "match";
			span[2] = "replace";
			span[3] = "split";
			span[4] = "extract";
			obj.Enum = list;
			dictionary["action"] = obj;
			dictionary["pattern"] = new ToolProperty
			{
				Type = "string",
				Description = "Regular expression pattern"
			};
			dictionary["text"] = new ToolProperty
			{
				Type = "string",
				Description = "Text to process"
			};
			dictionary["replacement"] = new ToolProperty
			{
				Type = "string",
				Description = "Replacement string for replace action (supports $1, $2, ${name})"
			};
			dictionary["flags"] = new ToolProperty
			{
				Type = "string",
				Description = "Regex flags: 'i' (ignore case), 'm' (multiline), 's' (singleline). Combine: 'im'"
			};
			toolParameterSchema.Properties = dictionary;
			num = 3;
			List<string> list2 = new List<string>(num);
			CollectionsMarshal.SetCount(list2, num);
			Span<string> span2 = CollectionsMarshal.AsSpan(list2);
			span2[0] = "action";
			span2[1] = "pattern";
			span2[2] = "text";
			toolParameterSchema.Required = list2;
			return toolParameterSchema;
		}
	}

	public Task<ToolResult> ExecuteAsync(JsonElement args, AgentContext context, CancellationToken ct = default(CancellationToken))
	{
		string text = args.GetProperty("action").GetString() ?? "";
		string pattern = args.GetProperty("pattern").GetString() ?? "";
		string text2 = args.GetProperty("text").GetString() ?? "";
		JsonElement value;
		string replacement = (args.TryGetProperty("replacement", out value) ? (value.GetString() ?? "") : "");
		JsonElement value2;
		string flags = (args.TryGetProperty("flags", out value2) ? (value2.GetString() ?? "") : "");
		try
		{
			RegexOptions options = ParseFlags(flags);
			Regex regex = new Regex(pattern, options, TimeSpan.FromMilliseconds(5000.0));
			if (1 == 0)
			{
			}
			ToolResult result = text switch
			{
				"test" => Test(regex, text2), 
				"match" => Match(regex, text2), 
				"replace" => Replace(regex, text2, replacement), 
				"split" => Split(regex, text2), 
				"extract" => Extract(regex, text2), 
				_ => ToolResult.Fail("Unknown action: " + text), 
			};
			if (1 == 0)
			{
			}
			return Task.FromResult(result);
		}
		catch (RegexMatchTimeoutException)
		{
			return Task.FromResult(ToolResult.Fail("정규식 실행 시간 초과 (ReDoS 방지). 패턴을 간소화하세요."));
		}
		catch (Exception ex2)
		{
			return Task.FromResult(ToolResult.Fail("정규식 오류: " + ex2.Message));
		}
	}

	private static RegexOptions ParseFlags(string flags)
	{
		RegexOptions regexOptions = RegexOptions.None;
		foreach (char c in flags)
		{
			RegexOptions regexOptions2 = regexOptions;
			if (1 == 0)
			{
			}
			RegexOptions regexOptions3 = c switch
			{
				'i' => RegexOptions.IgnoreCase, 
				'm' => RegexOptions.Multiline, 
				's' => RegexOptions.Singleline, 
				_ => RegexOptions.None, 
			};
			if (1 == 0)
			{
			}
			regexOptions = regexOptions2 | regexOptions3;
		}
		return regexOptions;
	}

	private static ToolResult Test(Regex regex, string text)
	{
		return ToolResult.Ok(regex.IsMatch(text) ? "✓ Pattern matches" : "✗ No match");
	}

	private static ToolResult Match(Regex regex, string text)
	{
		MatchCollection matchCollection = regex.Matches(text);
		if (matchCollection.Count == 0)
		{
			return ToolResult.Ok("No matches found.");
		}
		StringBuilder stringBuilder = new StringBuilder();
		StringBuilder stringBuilder2 = stringBuilder;
		StringBuilder stringBuilder3 = stringBuilder2;
		StringBuilder.AppendInterpolatedStringHandler handler = new StringBuilder.AppendInterpolatedStringHandler(17, 1, stringBuilder2);
		handler.AppendLiteral("Found ");
		handler.AppendFormatted(matchCollection.Count);
		handler.AppendLiteral(" match(es):");
		stringBuilder3.AppendLine(ref handler);
		int num = Math.Min(matchCollection.Count, 50);
		for (int i = 0; i < num; i++)
		{
			Match match = matchCollection[i];
			stringBuilder2 = stringBuilder;
			StringBuilder stringBuilder4 = stringBuilder2;
			handler = new StringBuilder.AppendInterpolatedStringHandler(24, 4, stringBuilder2);
			handler.AppendLiteral("\n[");
			handler.AppendFormatted(i);
			handler.AppendLiteral("] \"");
			handler.AppendFormatted(Truncate(match.Value, 200));
			handler.AppendLiteral("\" (index ");
			handler.AppendFormatted(match.Index);
			handler.AppendLiteral(", length ");
			handler.AppendFormatted(match.Length);
			handler.AppendLiteral(")");
			stringBuilder4.AppendLine(ref handler);
			if (match.Groups.Count > 1)
			{
				for (int j = 1; j < match.Groups.Count; j++)
				{
					Group obj = match.Groups[j];
					string text2 = regex.GroupNameFromNumber(j);
					string value = ((text2 != j.ToString()) ? ("'" + text2 + "'") : $"${j}");
					stringBuilder2 = stringBuilder;
					StringBuilder stringBuilder5 = stringBuilder2;
					handler = new StringBuilder.AppendInterpolatedStringHandler(14, 2, stringBuilder2);
					handler.AppendLiteral("    Group ");
					handler.AppendFormatted(value);
					handler.AppendLiteral(": \"");
					handler.AppendFormatted(Truncate(obj.Value, 100));
					handler.AppendLiteral("\"");
					stringBuilder5.AppendLine(ref handler);
				}
			}
		}
		if (matchCollection.Count > num)
		{
			stringBuilder2 = stringBuilder;
			StringBuilder stringBuilder6 = stringBuilder2;
			handler = new StringBuilder.AppendInterpolatedStringHandler(22, 1, stringBuilder2);
			handler.AppendLiteral("\n... and ");
			handler.AppendFormatted(matchCollection.Count - num);
			handler.AppendLiteral(" more matches");
			stringBuilder6.AppendLine(ref handler);
		}
		return ToolResult.Ok(stringBuilder.ToString());
	}

	private static ToolResult Replace(Regex regex, string text, string replacement)
	{
		string text2 = regex.Replace(text, replacement);
		int count = regex.Matches(text).Count;
		if (text2.Length > 8000)
		{
			text2 = text2.Substring(0, 8000) + "\n... (truncated)";
		}
		return ToolResult.Ok($"Replaced {count} occurrence(s):\n\n{text2}");
	}

	private static ToolResult Split(Regex regex, string text)
	{
		string[] array = regex.Split(text);
		StringBuilder stringBuilder = new StringBuilder();
		StringBuilder stringBuilder2 = stringBuilder;
		StringBuilder stringBuilder3 = stringBuilder2;
		StringBuilder.AppendInterpolatedStringHandler handler = new StringBuilder.AppendInterpolatedStringHandler(18, 1, stringBuilder2);
		handler.AppendLiteral("Split into ");
		handler.AppendFormatted(array.Length);
		handler.AppendLiteral(" parts:");
		stringBuilder3.AppendLine(ref handler);
		int num = Math.Min(array.Length, 100);
		for (int i = 0; i < num; i++)
		{
			stringBuilder2 = stringBuilder;
			StringBuilder stringBuilder4 = stringBuilder2;
			handler = new StringBuilder.AppendInterpolatedStringHandler(7, 2, stringBuilder2);
			handler.AppendLiteral("  [");
			handler.AppendFormatted(i);
			handler.AppendLiteral("] \"");
			handler.AppendFormatted(Truncate(array[i], 200));
			handler.AppendLiteral("\"");
			stringBuilder4.AppendLine(ref handler);
		}
		if (array.Length > num)
		{
			stringBuilder2 = stringBuilder;
			StringBuilder stringBuilder5 = stringBuilder2;
			handler = new StringBuilder.AppendInterpolatedStringHandler(20, 1, stringBuilder2);
			handler.AppendLiteral("\n... and ");
			handler.AppendFormatted(array.Length - num);
			handler.AppendLiteral(" more parts");
			stringBuilder5.AppendLine(ref handler);
		}
		return ToolResult.Ok(stringBuilder.ToString());
	}

	private static ToolResult Extract(Regex regex, string text)
	{
		Match match = regex.Match(text);
		if (!match.Success)
		{
			return ToolResult.Ok("No match found.");
		}
		StringBuilder stringBuilder = new StringBuilder();
		StringBuilder stringBuilder2 = stringBuilder;
		StringBuilder stringBuilder3 = stringBuilder2;
		StringBuilder.AppendInterpolatedStringHandler handler = new StringBuilder.AppendInterpolatedStringHandler(9, 1, stringBuilder2);
		handler.AppendLiteral("Match: \"");
		handler.AppendFormatted(Truncate(match.Value, 300));
		handler.AppendLiteral("\"");
		stringBuilder3.AppendLine(ref handler);
		if (match.Groups.Count > 1)
		{
			stringBuilder.AppendLine("\nGroups:");
			for (int i = 1; i < match.Groups.Count; i++)
			{
				Group obj = match.Groups[i];
				string text2 = regex.GroupNameFromNumber(i);
				string value = ((text2 != i.ToString()) ? ("'" + text2 + "'") : $"${i}");
				stringBuilder2 = stringBuilder;
				StringBuilder stringBuilder4 = stringBuilder2;
				handler = new StringBuilder.AppendInterpolatedStringHandler(6, 2, stringBuilder2);
				handler.AppendLiteral("  ");
				handler.AppendFormatted(value);
				handler.AppendLiteral(": \"");
				handler.AppendFormatted(Truncate(obj.Value, 200));
				handler.AppendLiteral("\"");
				stringBuilder4.AppendLine(ref handler);
			}
		}
		return ToolResult.Ok(stringBuilder.ToString());
	}

	private static string Truncate(string s, int maxLen)
	{
		return (s.Length <= maxLen) ? s : (s.Substring(0, maxLen) + "…");
	}
}
