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;
using System.Windows;

namespace AxCopilot.Services.Agent;

public class MemoryTool : IAgentTool
{
	public string Name => "memory";

	public string Description => "프로젝트 규칙, 사용자 선호도, 학습 내용을 저장하고 검색합니다.\n대화 간 지속되는 메모리로, 새 대화에서도 이전에 학습한 내용을 활용할 수 있습니다.\n- action=\"save\": 새 메모리 저장 (type, content 필수)\n- action=\"search\": 관련 메모리 검색 (query 필수)\n- action=\"list\": 현재 메모리 전체 목록\n- action=\"delete\": 메모리 삭제 (id 필수)\ntype 종류: rule(프로젝트 규칙), preference(사용자 선호), fact(사실), correction(실수 교정)";

	public ToolParameterSchema Parameters
	{
		get
		{
			ToolParameterSchema obj = new ToolParameterSchema
			{
				Properties = new Dictionary<string, ToolProperty>
				{
					["action"] = new ToolProperty
					{
						Type = "string",
						Description = "save | search | list | delete"
					},
					["type"] = new ToolProperty
					{
						Type = "string",
						Description = "메모리 유형: rule | preference | fact | correction. save 시 필수."
					},
					["content"] = new ToolProperty
					{
						Type = "string",
						Description = "저장할 내용. save 시 필수."
					},
					["query"] = new ToolProperty
					{
						Type = "string",
						Description = "검색 쿼리. search 시 필수."
					},
					["id"] = new ToolProperty
					{
						Type = "string",
						Description = "메모리 ID. delete 시 필수."
					}
				}
			};
			int num = 1;
			List<string> list = new List<string>(num);
			CollectionsMarshal.SetCount(list, num);
			CollectionsMarshal.AsSpan(list)[0] = "action";
			obj.Required = list;
			return obj;
		}
	}

	public Task<ToolResult> ExecuteAsync(JsonElement args, AgentContext context, CancellationToken ct = default(CancellationToken))
	{
		App app = Application.Current as App;
		if (!(app?.SettingsService?.Settings.Llm.EnableAgentMemory ?? true))
		{
			return Task.FromResult(ToolResult.Ok("에이전트 메모리가 비활성 상태입니다. 설정에서 활성화하세요."));
		}
		AgentMemoryService agentMemoryService = app?.MemoryService;
		if (agentMemoryService == null)
		{
			return Task.FromResult(ToolResult.Fail("메모리 서비스를 사용할 수 없습니다."));
		}
		if (!args.TryGetProperty("action", out var value))
		{
			return Task.FromResult(ToolResult.Fail("action이 필요합니다."));
		}
		string text = value.GetString() ?? "";
		if (1 == 0)
		{
		}
		ToolResult result = text switch
		{
			"save" => ExecuteSave(args, agentMemoryService, context), 
			"search" => ExecuteSearch(args, agentMemoryService), 
			"list" => ExecuteList(agentMemoryService), 
			"delete" => ExecuteDelete(args, agentMemoryService), 
			_ => ToolResult.Fail("알 수 없는 액션: " + text + ". save | search | list | delete 중 선택하세요."), 
		};
		if (1 == 0)
		{
		}
		return Task.FromResult(result);
	}

	private static ToolResult ExecuteSave(JsonElement args, AgentMemoryService svc, AgentContext context)
	{
		JsonElement value;
		string text = (args.TryGetProperty("type", out value) ? (value.GetString() ?? "fact") : "fact");
		JsonElement value2;
		string text2 = (args.TryGetProperty("content", out value2) ? (value2.GetString() ?? "") : "");
		if (string.IsNullOrWhiteSpace(text2))
		{
			return ToolResult.Fail("content가 필요합니다.");
		}
		string[] source = new string[4] { "rule", "preference", "fact", "correction" };
		if (!source.Contains(text))
		{
			return ToolResult.Fail("잘못된 type: " + text + ". rule | preference | fact | correction 중 선택하세요.");
		}
		string workFolder = (string.IsNullOrEmpty(context.WorkFolder) ? null : context.WorkFolder);
		MemoryEntry memoryEntry = svc.Add(text, text2, "agent:" + context.ActiveTab, workFolder);
		return ToolResult.Ok($"메모리 저장됨 [{memoryEntry.Type}] (ID: {memoryEntry.Id}): {memoryEntry.Content}");
	}

	private static ToolResult ExecuteSearch(JsonElement args, AgentMemoryService svc)
	{
		JsonElement value;
		string text = (args.TryGetProperty("query", out value) ? (value.GetString() ?? "") : "");
		if (string.IsNullOrWhiteSpace(text))
		{
			return ToolResult.Fail("query가 필요합니다.");
		}
		List<MemoryEntry> relevant = svc.GetRelevant(text);
		if (relevant.Count == 0)
		{
			return ToolResult.Ok("관련 메모리가 없습니다.");
		}
		StringBuilder stringBuilder = new StringBuilder();
		StringBuilder stringBuilder2 = stringBuilder;
		StringBuilder stringBuilder3 = stringBuilder2;
		StringBuilder.AppendInterpolatedStringHandler handler = new StringBuilder.AppendInterpolatedStringHandler(9, 1, stringBuilder2);
		handler.AppendLiteral("관련 메모리 ");
		handler.AppendFormatted(relevant.Count);
		handler.AppendLiteral("개:");
		stringBuilder3.AppendLine(ref handler);
		foreach (MemoryEntry item in relevant)
		{
			stringBuilder2 = stringBuilder;
			StringBuilder stringBuilder4 = stringBuilder2;
			handler = new StringBuilder.AppendInterpolatedStringHandler(18, 4, stringBuilder2);
			handler.AppendLiteral("  [");
			handler.AppendFormatted(item.Type);
			handler.AppendLiteral("] ");
			handler.AppendFormatted(item.Content);
			handler.AppendLiteral(" (사용 ");
			handler.AppendFormatted(item.UseCount);
			handler.AppendLiteral("회, ID: ");
			handler.AppendFormatted(item.Id);
			handler.AppendLiteral(")");
			stringBuilder4.AppendLine(ref handler);
		}
		return ToolResult.Ok(stringBuilder.ToString());
	}

	private static ToolResult ExecuteList(AgentMemoryService svc)
	{
		IReadOnlyList<MemoryEntry> all = svc.All;
		if (all.Count == 0)
		{
			return ToolResult.Ok("저장된 메모리가 없습니다.");
		}
		StringBuilder stringBuilder = new StringBuilder();
		StringBuilder stringBuilder2 = stringBuilder;
		StringBuilder stringBuilder3 = stringBuilder2;
		StringBuilder.AppendInterpolatedStringHandler handler = new StringBuilder.AppendInterpolatedStringHandler(9, 1, stringBuilder2);
		handler.AppendLiteral("전체 메모리 ");
		handler.AppendFormatted(all.Count);
		handler.AppendLiteral("개:");
		stringBuilder3.AppendLine(ref handler);
		foreach (IGrouping<string, MemoryEntry> item in from e in all
			group e by e.Type)
		{
			stringBuilder2 = stringBuilder;
			StringBuilder stringBuilder4 = stringBuilder2;
			handler = new StringBuilder.AppendInterpolatedStringHandler(3, 1, stringBuilder2);
			handler.AppendLiteral("\n[");
			handler.AppendFormatted(item.Key);
			handler.AppendLiteral("]");
			stringBuilder4.AppendLine(ref handler);
			foreach (MemoryEntry item2 in item.OrderByDescending((MemoryEntry e) => e.UseCount))
			{
				stringBuilder2 = stringBuilder;
				StringBuilder stringBuilder5 = stringBuilder2;
				handler = new StringBuilder.AppendInterpolatedStringHandler(17, 3, stringBuilder2);
				handler.AppendLiteral("  • ");
				handler.AppendFormatted(item2.Content);
				handler.AppendLiteral(" (사용 ");
				handler.AppendFormatted(item2.UseCount);
				handler.AppendLiteral("회, ID: ");
				handler.AppendFormatted(item2.Id);
				handler.AppendLiteral(")");
				stringBuilder5.AppendLine(ref handler);
			}
		}
		return ToolResult.Ok(stringBuilder.ToString());
	}

	private static ToolResult ExecuteDelete(JsonElement args, AgentMemoryService svc)
	{
		JsonElement value;
		string text = (args.TryGetProperty("id", out value) ? (value.GetString() ?? "") : "");
		if (string.IsNullOrWhiteSpace(text))
		{
			return ToolResult.Fail("id가 필요합니다.");
		}
		return svc.Remove(text) ? ToolResult.Ok("메모리 삭제됨 (ID: " + text + ")") : ToolResult.Fail("해당 ID의 메모리를 찾을 수 없습니다: " + text);
	}
}
