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

namespace AxCopilot.Services.Agent;

public class JsonTool : IAgentTool
{
	private record PathSegment(string Key, int Index, bool IsIndex);

	public string Name => "json_tool";

	public string Description => "JSON processing tool. Actions: 'validate' — check if text is valid JSON and report errors; 'format' — pretty-print or minify JSON; 'query' — extract value by dot-path (e.g. 'data.users[0].name'); 'keys' — list top-level keys; 'convert' — convert between JSON/CSV (flat arrays only).";

	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] = "validate";
			span[1] = "format";
			span[2] = "query";
			span[3] = "keys";
			span[4] = "convert";
			obj.Enum = list;
			dictionary["action"] = obj;
			dictionary["json"] = new ToolProperty
			{
				Type = "string",
				Description = "JSON text to process"
			};
			dictionary["path"] = new ToolProperty
			{
				Type = "string",
				Description = "Dot-path for query action (e.g. 'data.items[0].name')"
			};
			dictionary["minify"] = new ToolProperty
			{
				Type = "string",
				Description = "For format action: 'true' to minify, 'false' to pretty-print (default)"
			};
			ToolProperty obj2 = new ToolProperty
			{
				Type = "string",
				Description = "For convert action: target format"
			};
			num = 1;
			List<string> list2 = new List<string>(num);
			CollectionsMarshal.SetCount(list2, num);
			CollectionsMarshal.AsSpan(list2)[0] = "csv";
			obj2.Enum = list2;
			dictionary["target_format"] = obj2;
			toolParameterSchema.Properties = dictionary;
			num = 2;
			List<string> list3 = new List<string>(num);
			CollectionsMarshal.SetCount(list3, num);
			Span<string> span2 = CollectionsMarshal.AsSpan(list3);
			span2[0] = "action";
			span2[1] = "json";
			toolParameterSchema.Required = list3;
			return toolParameterSchema;
		}
	}

	public Task<ToolResult> ExecuteAsync(JsonElement args, AgentContext context, CancellationToken ct = default(CancellationToken))
	{
		string text = args.GetProperty("action").GetString() ?? "";
		string json = args.GetProperty("json").GetString() ?? "";
		try
		{
			if (1 == 0)
			{
			}
			JsonElement value;
			JsonElement value2;
			JsonElement value3;
			ToolResult result = text switch
			{
				"validate" => Validate(json), 
				"format" => Format(json, args.TryGetProperty("minify", out value) && value.GetString() == "true"), 
				"query" => Query(json, args.TryGetProperty("path", out value2) ? (value2.GetString() ?? "") : ""), 
				"keys" => Keys(json), 
				"convert" => Convert(json, args.TryGetProperty("target_format", out value3) ? (value3.GetString() ?? "csv") : "csv"), 
				_ => ToolResult.Fail("Unknown action: " + text), 
			};
			if (1 == 0)
			{
			}
			return Task.FromResult(result);
		}
		catch (Exception ex)
		{
			return Task.FromResult(ToolResult.Fail("JSON 처리 오류: " + ex.Message));
		}
	}

	private static ToolResult Validate(string json)
	{
		try
		{
			using JsonDocument jsonDocument = JsonDocument.Parse(json);
			JsonElement rootElement = jsonDocument.RootElement;
			JsonValueKind valueKind = rootElement.ValueKind;
			if (1 == 0)
			{
			}
			string text = valueKind switch
			{
				JsonValueKind.Object => $"Object ({rootElement.EnumerateObject().Count()} keys)", 
				JsonValueKind.Array => $"Array ({rootElement.GetArrayLength()} items)", 
				_ => rootElement.ValueKind.ToString(), 
			};
			if (1 == 0)
			{
			}
			string text2 = text;
			return ToolResult.Ok("✓ Valid JSON — " + text2);
		}
		catch (JsonException ex)
		{
			return ToolResult.Ok("✗ Invalid JSON — " + ex.Message);
		}
	}

	private static ToolResult Format(string json, bool minify)
	{
		using JsonDocument jsonDocument = JsonDocument.Parse(json);
		JsonSerializerOptions options = new JsonSerializerOptions
		{
			WriteIndented = !minify
		};
		string text = JsonSerializer.Serialize(jsonDocument.RootElement, options);
		if (text.Length > 8000)
		{
			text = text.Substring(0, 8000) + "\n... (truncated)";
		}
		return ToolResult.Ok(text);
	}

	private static ToolResult Query(string json, string path)
	{
		if (string.IsNullOrEmpty(path))
		{
			return ToolResult.Fail("path parameter is required for query action");
		}
		using JsonDocument jsonDocument = JsonDocument.Parse(json);
		JsonElement value = jsonDocument.RootElement;
		foreach (PathSegment item in ParsePath(path))
		{
			if (item.IsIndex)
			{
				if (value.ValueKind != JsonValueKind.Array || item.Index >= value.GetArrayLength())
				{
					return ToolResult.Fail($"Array index [{item.Index}] out of range");
				}
				value = value[item.Index];
			}
			else
			{
				if (value.ValueKind != JsonValueKind.Object || !value.TryGetProperty(item.Key, out var value2))
				{
					return ToolResult.Fail("Key '" + item.Key + "' not found");
				}
				value = value2;
			}
		}
		JsonValueKind valueKind = value.ValueKind;
		if (1 == 0)
		{
		}
		string text = valueKind switch
		{
			JsonValueKind.String => value.GetString() ?? "", 
			JsonValueKind.Number => value.GetRawText(), 
			JsonValueKind.True => "true", 
			JsonValueKind.False => "false", 
			JsonValueKind.Null => "null", 
			_ => JsonSerializer.Serialize(value, new JsonSerializerOptions
			{
				WriteIndented = true
			}), 
		};
		if (1 == 0)
		{
		}
		string text2 = text;
		if (text2.Length > 5000)
		{
			text2 = text2.Substring(0, 5000) + "\n... (truncated)";
		}
		return ToolResult.Ok(text2);
	}

	private static ToolResult Keys(string json)
	{
		using JsonDocument jsonDocument = JsonDocument.Parse(json);
		if (jsonDocument.RootElement.ValueKind != JsonValueKind.Object)
		{
			return ToolResult.Fail("Root element is not an object");
		}
		IEnumerable<string> values = jsonDocument.RootElement.EnumerateObject().Select(delegate(JsonProperty p)
		{
			JsonValueKind valueKind = p.Value.ValueKind;
			if (1 == 0)
			{
			}
			string text;
			switch (valueKind)
			{
			case JsonValueKind.Object:
				text = "object";
				break;
			case JsonValueKind.Array:
				text = $"array[{p.Value.GetArrayLength()}]";
				break;
			case JsonValueKind.String:
				text = "string";
				break;
			case JsonValueKind.Number:
				text = "number";
				break;
			case JsonValueKind.True:
			case JsonValueKind.False:
				text = "boolean";
				break;
			default:
				text = "null";
				break;
			}
			if (1 == 0)
			{
			}
			string text2 = text;
			return "  " + p.Name + ": " + text2;
		});
		return ToolResult.Ok($"Keys ({jsonDocument.RootElement.EnumerateObject().Count()}):\n{string.Join("\n", values)}");
	}

	private static ToolResult Convert(string json, string targetFormat)
	{
		if (targetFormat != "csv")
		{
			return ToolResult.Fail("Unsupported target format: " + targetFormat);
		}
		using JsonDocument jsonDocument = JsonDocument.Parse(json);
		if (jsonDocument.RootElement.ValueKind != JsonValueKind.Array)
		{
			return ToolResult.Fail("JSON must be an array for CSV conversion");
		}
		JsonElement rootElement = jsonDocument.RootElement;
		if (rootElement.GetArrayLength() == 0)
		{
			return ToolResult.Ok("(empty array)");
		}
		List<string> list = new List<string>();
		foreach (JsonElement item2 in rootElement.EnumerateArray())
		{
			if (item2.ValueKind != JsonValueKind.Object)
			{
				return ToolResult.Fail("All array items must be objects for CSV conversion");
			}
			foreach (JsonProperty item3 in item2.EnumerateObject())
			{
				if (!list.Contains(item3.Name))
				{
					list.Add(item3.Name);
				}
			}
		}
		StringBuilder stringBuilder = new StringBuilder();
		stringBuilder.AppendLine(string.Join(",", list.Select((string k) => "\"" + k + "\"")));
		foreach (JsonElement item in rootElement.EnumerateArray())
		{
			JsonElement value;
			IEnumerable<string> values = list.Select((string k) => (!item.TryGetProperty(k, out value)) ? "\"\"" : ((value.ValueKind == JsonValueKind.String) ? ("\"" + value.GetString()?.Replace("\"", "\"\"") + "\"") : value.GetRawText()));
			stringBuilder.AppendLine(string.Join(",", values));
		}
		string text = stringBuilder.ToString();
		if (text.Length > 8000)
		{
			text = text.Substring(0, 8000) + "\n... (truncated)";
		}
		return ToolResult.Ok(text);
	}

	private static List<PathSegment> ParsePath(string path)
	{
		List<PathSegment> list = new List<PathSegment>();
		string[] array = path.Split('.');
		foreach (string text in array)
		{
			int num = text.IndexOf('[');
			if (num >= 0)
			{
				string text2 = text.Substring(0, num);
				if (!string.IsNullOrEmpty(text2))
				{
					list.Add(new PathSegment(text2, 0, IsIndex: false));
				}
				string text3 = text;
				int num2 = num + 1;
				string s = text3.Substring(num2, text3.Length - num2).TrimEnd(']');
				if (int.TryParse(s, out var result))
				{
					list.Add(new PathSegment("", result, IsIndex: true));
				}
			}
			else
			{
				list.Add(new PathSegment(text, 0, IsIndex: false));
			}
		}
		return list;
	}
}
