using System.Text;
using System.Text.Json;

namespace AxCopilot.Services.Agent;

/// <summary>
/// 에이전트 메모리 관리 도구.
/// 프로젝트 규칙, 사용자 선호도, 학습 내용을 저장/검색/삭제합니다.
/// </summary>
public class MemoryTool : IAgentTool
{
    private static App? CurrentApp => System.Windows.Application.Current as App;

    public string Name => "memory";

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

    public ToolParameterSchema Parameters => new()
    {
        Properties = new()
        {
            ["action"] = new() { Type = "string", Description = "save | search | list | delete" },
            ["type"] = new() { Type = "string", Description = "메모리 유형: rule | preference | fact | correction. save 시 필수." },
            ["content"] = new() { Type = "string", Description = "저장할 내용. save 시 필수." },
            ["query"] = new() { Type = "string", Description = "검색 쿼리. search 시 필수." },
            ["id"] = new() { Type = "string", Description = "메모리 ID. delete 시 필수." },
        },
        Required = ["action"]
    };

    public Task<ToolResult> ExecuteAsync(JsonElement args, AgentContext context, CancellationToken ct = default)
    {
        // 설정 체크
        if (!(context.Llm?.EnableAgentMemory ?? true))
            return Task.FromResult(ToolResult.Ok("에이전트 메모리가 비활성 상태입니다. 설정에서 활성화하세요."));

        var memoryService = CurrentApp?.MemoryService;
        if (memoryService == null)
            return Task.FromResult(ToolResult.Fail("메모리 서비스를 사용할 수 없습니다."));

        if (!args.TryGetProperty("action", out var actionEl))
            return Task.FromResult(ToolResult.Fail("action이 필요합니다."));
        var action = actionEl.GetString() ?? "";

        return Task.FromResult(action switch
        {
            "save" => ExecuteSave(args, memoryService, context),
            "search" => ExecuteSearch(args, memoryService),
            "list" => ExecuteList(memoryService),
            "delete" => ExecuteDelete(args, memoryService),
            _ => ToolResult.Fail($"알 수 없는 액션: {action}. save | search | list | delete 중 선택하세요."),
        });
    }

    private static ToolResult ExecuteSave(JsonElement args, AgentMemoryService svc, AgentContext context)
    {
        var type = args.TryGetProperty("type", out var t) ? t.GetString() ?? "fact" : "fact";
        var content = args.TryGetProperty("content", out var c) ? c.GetString() ?? "" : "";

        if (string.IsNullOrWhiteSpace(content))
            return ToolResult.Fail("content가 필요합니다.");

        var validTypes = new[] { "rule", "preference", "fact", "correction" };
        if (!validTypes.Contains(type))
            return ToolResult.Fail($"잘못된 type: {type}. rule | preference | fact | correction 중 선택하세요.");

        var workFolder = string.IsNullOrEmpty(context.WorkFolder) ? null : context.WorkFolder;
        var entry = svc.Add(type, content, $"agent:{context.ActiveTab}", workFolder);
        return ToolResult.Ok($"메모리 저장됨 [{entry.Type}] (ID: {entry.Id}): {entry.Content}");
    }

    private static ToolResult ExecuteSearch(JsonElement args, AgentMemoryService svc)
    {
        var query = args.TryGetProperty("query", out var q) ? q.GetString() ?? "" : "";
        if (string.IsNullOrWhiteSpace(query))
            return ToolResult.Fail("query가 필요합니다.");

        var results = svc.GetRelevant(query, 10);
        if (results.Count == 0)
            return ToolResult.Ok("관련 메모리가 없습니다.");

        var sb = new StringBuilder();
        sb.AppendLine($"관련 메모리 {results.Count}개:");
        foreach (var e in results)
            sb.AppendLine($"  [{e.Type}] {e.Content} (사용 {e.UseCount}회, ID: {e.Id})");
        return ToolResult.Ok(sb.ToString());
    }

    private static ToolResult ExecuteList(AgentMemoryService svc)
    {
        var all = svc.All;
        if (all.Count == 0)
            return ToolResult.Ok("저장된 메모리가 없습니다.");

        var sb = new StringBuilder();
        sb.AppendLine($"전체 메모리 {all.Count}개:");
        foreach (var group in all.GroupBy(e => e.Type))
        {
            sb.AppendLine($"\n[{group.Key}]");
            foreach (var e in group.OrderByDescending(e => e.UseCount))
                sb.AppendLine($"  • {e.Content} (사용 {e.UseCount}회, ID: {e.Id})");
        }
        return ToolResult.Ok(sb.ToString());
    }

    private static ToolResult ExecuteDelete(JsonElement args, AgentMemoryService svc)
    {
        var id = args.TryGetProperty("id", out var i) ? i.GetString() ?? "" : "";
        if (string.IsNullOrWhiteSpace(id))
            return ToolResult.Fail("id가 필요합니다.");

        return svc.Remove(id)
            ? ToolResult.Ok($"메모리 삭제됨 (ID: {id})")
            : ToolResult.Fail($"해당 ID의 메모리를 찾을 수 없습니다: {id}");
    }
}
