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

namespace AxCopilot.Services.Agent;

/// <summary>파일/폴더 이동·복사·이름변경·삭제·디렉토리 생성 도구.</summary>
public class FileManageTool : IAgentTool
{
    public string Name => "file_manage";
    public string Description =>
        "Manage files and directories. Actions: " +
        "'move' — move file/folder to destination; " +
        "'copy' — copy file/folder to destination; " +
        "'rename' — rename file/folder; " +
        "'delete' — delete file (requires Ask permission); " +
        "'mkdir' — create directory recursively.";

    public ToolParameterSchema Parameters => new()
    {
        Properties = new()
        {
            ["action"] = new()
            {
                Type = "string",
                Description = "Action to perform",
                Enum = ["move", "copy", "rename", "delete", "mkdir"],
            },
            ["path"] = new()
            {
                Type = "string",
                Description = "Source file/folder path",
            },
            ["destination"] = new()
            {
                Type = "string",
                Description = "Destination path (for move/copy/rename)",
            },
        },
        Required = ["action", "path"],
    };

    public async Task<ToolResult> ExecuteAsync(JsonElement args, AgentContext context, CancellationToken ct = default)
    {
        var action = args.GetProperty("action").GetString() ?? "";
        var rawPath = args.GetProperty("path").GetString() ?? "";
        var dest = args.TryGetProperty("destination", out var d) ? d.GetString() ?? "" : "";

        var path = Path.IsPathRooted(rawPath) ? rawPath : Path.Combine(context.WorkFolder, rawPath);

        if (!context.IsPathAllowed(path))
            return ToolResult.Fail($"경로 접근 차단: {path}");

        try
        {
            switch (action)
            {
                case "mkdir":
                    Directory.CreateDirectory(path);
                    return ToolResult.Ok($"디렉토리 생성: {path}");

                case "delete":
                    if (context.AskPermission != null)
                    {
                        var allowed = await context.AskPermission("file_manage(delete)", path);
                        if (!allowed) return ToolResult.Fail("사용자가 삭제를 거부했습니다.");
                    }
                    if (File.Exists(path))
                    {
                        File.Delete(path);
                        return ToolResult.Ok($"파일 삭제: {path}", filePath: path);
                    }
                    if (Directory.Exists(path))
                    {
                        Directory.Delete(path, recursive: true);
                        return ToolResult.Ok($"폴더 삭제: {path}", filePath: path);
                    }
                    return ToolResult.Fail($"경로를 찾을 수 없습니다: {path}");

                case "move":
                case "copy":
                case "rename":
                    if (string.IsNullOrEmpty(dest))
                        return ToolResult.Fail($"'{action}' 작업에는 'destination'이 필요합니다.");

                    var destPath = Path.IsPathRooted(dest) ? dest : Path.Combine(context.WorkFolder, dest);
                    if (!context.IsPathAllowed(destPath))
                        return ToolResult.Fail($"대상 경로 접근 차단: {destPath}");

                    // 대상 디렉토리 자동 생성
                    var destDir = Path.GetDirectoryName(destPath);
                    if (!string.IsNullOrEmpty(destDir) && !Directory.Exists(destDir))
                        Directory.CreateDirectory(destDir);

                    if (action == "rename")
                    {
                        // rename: 같은 폴더 내 이름 변경
                        var dir = Path.GetDirectoryName(path) ?? context.WorkFolder;
                        destPath = Path.Combine(dir, dest);
                    }

                    if (File.Exists(path))
                    {
                        if (action == "copy")
                            File.Copy(path, destPath, overwrite: true);
                        else
                            File.Move(path, destPath, overwrite: true);
                        return ToolResult.Ok($"{action}: {path} → {destPath}", filePath: destPath);
                    }
                    if (Directory.Exists(path))
                    {
                        if (action == "copy")
                            CopyDirectory(path, destPath);
                        else
                            Directory.Move(path, destPath);
                        return ToolResult.Ok($"{action}: {path} → {destPath}", filePath: destPath);
                    }
                    return ToolResult.Fail($"소스 경로를 찾을 수 없습니다: {path}");

                default:
                    return ToolResult.Fail($"Unknown action: {action}");
            }
        }
        catch (Exception ex)
        {
            return ToolResult.Fail($"파일 관리 오류: {ex.Message}");
        }
    }

    private static void CopyDirectory(string src, string dst)
    {
        Directory.CreateDirectory(dst);
        foreach (var file in Directory.GetFiles(src))
            File.Copy(file, Path.Combine(dst, Path.GetFileName(file)), true);
        foreach (var dir in Directory.GetDirectories(src))
            CopyDirectory(dir, Path.Combine(dst, Path.GetFileName(dir)));
    }
}
