using System.IO;
using System.Security.Cryptography;
using System.Text;
using System.Text.Json;

namespace AxCopilot.Services.Agent;

/// <summary>파일·텍스트 MD5/SHA256 해시 계산 도구.</summary>
public class HashTool : IAgentTool
{
    public string Name => "hash_tool";
    public string Description =>
        "Compute hash digests for text or files. " +
        "Supports MD5, SHA1, SHA256, SHA512. " +
        "Use 'text' mode for inline text or 'file' mode for file path.";

    public ToolParameterSchema Parameters => new()
    {
        Properties = new()
        {
            ["mode"] = new()
            {
                Type = "string",
                Description = "Input mode",
                Enum = ["text", "file"],
            },
            ["input"] = new()
            {
                Type = "string",
                Description = "Text to hash or file path",
            },
            ["algorithm"] = new()
            {
                Type = "string",
                Description = "Hash algorithm (default: sha256)",
                Enum = ["md5", "sha1", "sha256", "sha512"],
            },
        },
        Required = ["mode", "input"],
    };

    public Task<ToolResult> ExecuteAsync(JsonElement args, AgentContext context, CancellationToken ct = default)
    {
        var mode = args.GetProperty("mode").GetString() ?? "text";
        var input = args.GetProperty("input").GetString() ?? "";
        var algo = args.TryGetProperty("algorithm", out var a) ? a.GetString() ?? "sha256" : "sha256";

        try
        {
            byte[] data;
            string label;

            if (mode == "file")
            {
                var path = Path.IsPathRooted(input) ? input : Path.Combine(context.WorkFolder, input);
                if (!File.Exists(path))
                    return Task.FromResult(ToolResult.Fail($"File not found: {path}"));
                data = File.ReadAllBytes(path);
                label = Path.GetFileName(path);
            }
            else
            {
                data = Encoding.UTF8.GetBytes(input);
                label = $"text ({data.Length} bytes)";
            }

            using var hasher = algo switch
            {
                "md5"    => (HashAlgorithm)MD5.Create(),
                "sha1"   => SHA1.Create(),
                "sha256" => SHA256.Create(),
                "sha512" => SHA512.Create(),
                _        => SHA256.Create(),
            };

            var hash = hasher.ComputeHash(data);
            var hex = BitConverter.ToString(hash).Replace("-", "").ToLowerInvariant();
            return Task.FromResult(ToolResult.Ok($"{algo.ToUpperInvariant()}({label}):\n{hex}"));
        }
        catch (Exception ex)
        {
            return Task.FromResult(ToolResult.Fail($"해시 오류: {ex.Message}"));
        }
    }
}
