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

namespace AxCopilot.Services.Agent;

/// <summary>파일 내용을 읽어 반환하는 도구.</summary>
public class FileReadTool : IAgentTool
{
    public string Name => "file_read";
    public string Description => "Read the contents of a file. Returns the text content with line numbers.";

    public ToolParameterSchema Parameters => new()
    {
        Properties = new()
        {
            ["path"] = new() { Type = "string", Description = "File path to read (absolute or relative to work folder)" },
            ["offset"] = new() { Type = "integer", Description = "Starting line number (1-based). Optional, default 1." },
            ["limit"] = new() { Type = "integer", Description = "Maximum number of lines to read. Optional, default 500." },
        },
        Required = ["path"]
    };

    public Task<ToolResult> ExecuteAsync(JsonElement args, AgentContext context, CancellationToken ct)
    {
        if (!args.TryGetProperty("path", out var pathEl))
            return Task.FromResult(ToolResult.Fail("path가 필요합니다."));
        var path = pathEl.GetString() ?? "";
        var offset = args.TryGetProperty("offset", out var ofs) ? ofs.GetInt32() : 1;
        var limit = args.TryGetProperty("limit", out var lim) ? lim.GetInt32() : 500;

        var fullPath = ResolvePath(path, context.WorkFolder);

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

        if (!File.Exists(fullPath))
            return Task.FromResult(ToolResult.Fail($"파일이 존재하지 않습니다: {fullPath}"));

        try
        {
            var lines = File.ReadAllLines(fullPath, Encoding.UTF8);
            var total = lines.Length;
            var startIdx = Math.Max(0, offset - 1);
            var endIdx = Math.Min(total, startIdx + limit);

            var sb = new StringBuilder();
            sb.AppendLine($"[{fullPath}] ({total} lines, showing {startIdx + 1}-{endIdx})");
            for (int i = startIdx; i < endIdx; i++)
                sb.AppendLine($"{i + 1,5}\t{lines[i]}");

            return Task.FromResult(ToolResult.Ok(sb.ToString(), fullPath));
        }
        catch (Exception ex)
        {
            return Task.FromResult(ToolResult.Fail($"파일 읽기 실패: {ex.Message}"));
        }
    }

    internal static string ResolvePath(string path, string workFolder)
    {
        if (Path.IsPathRooted(path)) return Path.GetFullPath(path);
        if (!string.IsNullOrEmpty(workFolder))
            return Path.GetFullPath(Path.Combine(workFolder, path));
        return Path.GetFullPath(path);
    }
}
