using System;

namespace OpenAI.Chat;

/// <summary>
///     A tool call made by the model.
///     <list>
///         <item>
///             Call <see cref="CreateFunctionToolCall(string, string, BinaryData)"/> to create a
///             <see cref="ChatToolCall"/> representing a function call made by the model.
///         </item>
///     </list>
/// </summary>
[CodeGenType("ChatCompletionMessageToolCall")]
[CodeGenSuppress("ChatToolCall", typeof(string), typeof(InternalChatCompletionMessageToolCallFunction))]
public partial class ChatToolCall
{
    // CUSTOM: Made internal.
    [CodeGenMember("Function")]
    internal InternalChatCompletionMessageToolCallFunction Function { get; set; }

    // CUSTOM: Public type applied..
    /// <summary> The kind of tool call. </summary>
    [CodeGenMember("Type")]
    public ChatToolCallKind Kind { get; } = ChatToolCallKind.Function;

    // CUSTOM: Spread.
    /// <summary> The name of the function that the model is calling. </summary>
    /// <remarks> Present when <see cref="Kind"/> is <see cref="ChatToolCallKind.Function"/>. </remarks>
    public string FunctionName => Function?.Name;

    // CUSTOM: Spread.
    /// <summary>
    ///     The arguments that the model is calling the function with, which are generated by the model in JSON format.
    ///     Note that the model does not always generate valid JSON, and may hallucinate parameters not defined by your
    ///     function schema. Validate the arguments in your code before calling your function.
    /// </summary>
    /// <remarks> Present when <see cref="Kind"/> is <see cref="ChatToolCallKind.Function"/>. </remarks>
    public BinaryData FunctionArguments => Function?.Arguments;

    /// <summary> Creates a new <see cref="ChatToolCall"/> representing a function call made by the model. </summary>
    /// <param name="id"> The ID of the tool call. </param>
    /// <param name="functionName"> The name of the function that model is calling. </param>
    /// <param name="functionArguments">
    ///     The arguments that model is calling the function with, which are generated by the model in JSON format.
    ///     Note that the model does not always generate valid JSON, and may hallucinate parameters not defined by your
    ///     function schema. Validate the arguments in your code before calling your function.
    /// </param>
    /// <exception cref="ArgumentNullException"> <paramref name="id"/>, <paramref name="functionName"/> or <paramref name="functionArguments"/> is null. </exception>
    /// <exception cref="ArgumentException"> <paramref name="id"/> or <paramref name="functionName"/> is an empty string, and was expected to be non-empty. </exception>
    public static ChatToolCall CreateFunctionToolCall(string id, string functionName, BinaryData functionArguments)
    {
        Argument.AssertNotNull(id, nameof(id));
        Argument.AssertNotNullOrEmpty(functionName, nameof(functionName));
        Argument.AssertNotNull(functionArguments, nameof(functionArguments));

        InternalChatCompletionMessageToolCallFunction function = new(functionName, functionArguments);

        return new(
            id: id,
            kind: ChatToolCallKind.Function,
            function: function,
            additionalBinaryDataProperties: null);
    }
}