using System.Text.Json;

namespace AxCopilot.Services.Agent;

/// <summary>에이전트가 사용자에게 질문하고 응답을 대기하는 도구.</summary>
public class UserAskTool : IAgentTool
{
    public string Name => "user_ask";
    public string Description =>
        "Ask the user a question and wait for their response. " +
        "Use when you need clarification, confirmation, or a choice from the user. " +
        "Optionally provide predefined options for the user to pick from. " +
        "The user can select from options OR type a custom response.";

    public ToolParameterSchema Parameters => new()
    {
        Properties = new()
        {
            ["question"] = new()
            {
                Type = "string",
                Description = "The question to ask the user",
            },
            ["options"] = new()
            {
                Type = "array",
                Description = "Optional list of choices for the user (e.g. ['Option A', 'Option B'])",
                Items = new() { Type = "string", Description = "Choice option" },
            },
            ["default_value"] = new()
            {
                Type = "string",
                Description = "Default value if user doesn't specify",
            },
        },
        Required = ["question"],
    };

    public async Task<ToolResult> ExecuteAsync(JsonElement args, AgentContext context, CancellationToken ct = default)
    {
        var question = args.GetProperty("question").GetString() ?? "";
        var defaultVal = args.TryGetProperty("default_value", out var dv) ? dv.GetString() ?? "" : "";

        var options = new List<string>();
        if (args.TryGetProperty("options", out var opts) && opts.ValueKind == JsonValueKind.Array)
        {
            foreach (var o in opts.EnumerateArray())
            {
                var s = o.GetString();
                if (!string.IsNullOrEmpty(s)) options.Add(s);
            }
        }

        // UserAskCallback 사용 (커스텀 대화 상자)
        if (context.UserAskCallback != null)
        {
            try
            {
                var response = await context.UserAskCallback(question, options, defaultVal);
                if (response == null)
                    return ToolResult.Fail("사용자가 응답을 취소했습니다.");

                return ToolResult.Ok($"사용자 응답: {response}");
            }
            catch (OperationCanceledException)
            {
                return ToolResult.Fail("사용자가 응답을 취소했습니다.");
            }
            catch (Exception ex)
            {
                return ToolResult.Fail($"사용자 입력 오류: {ex.Message}");
            }
        }

        // 폴백: UserDecision 콜백
        if (context.UserDecision != null)
        {
            try
            {
                var prompt = question;
                if (!string.IsNullOrEmpty(defaultVal))
                    prompt += $"\n(기본값: {defaultVal})";

                var effectiveOptions = options.Count > 0 ? options : new List<string> { "확인" };
                var response = await context.UserDecision(prompt, effectiveOptions);

                if (string.IsNullOrEmpty(response) && !string.IsNullOrEmpty(defaultVal))
                    response = defaultVal;

                return ToolResult.Ok($"사용자 응답: {response}");
            }
            catch (OperationCanceledException)
            {
                return ToolResult.Fail("사용자가 응답을 취소했습니다.");
            }
            catch (Exception ex)
            {
                return ToolResult.Fail($"사용자 입력 오류: {ex.Message}");
            }
        }

        return ToolResult.Fail("사용자 입력 콜백이 등록되지 않았습니다.");
    }
}
