// Copyright (c) Microsoft. All rights reserved.

using System.Collections.Generic;
using System.Text.Json.Serialization;

namespace Microsoft.Agents.AI.Hosting.OpenAI.ChatCompletions.Models;

/// <summary>
/// Represents a chunk of chat completion response returned by the model, based on the provided input.
/// </summary>
internal sealed record ChatCompletionChunk
{
    /// <summary>
    /// A unique identifier for the chat completion. Each chunk has the same ID.
    /// </summary>
    [JsonPropertyName("id")]
    [JsonRequired]
    public required string Id { get; init; }

    /// <summary>
    /// A list of chat completion choices. Can be more than one if n is greater than 1.
    /// </summary>
    [JsonPropertyName("choices")]
    [JsonRequired]
    public required IList<ChatCompletionChoiceChunk> Choices { get; init; }

    /// <summary>
    /// The object type, which is always "chat.completion.chunk".
    /// </summary>
    [JsonPropertyName("object")]
    public string Object => "chat.completion.chunk";

    /// <summary>
    /// The Unix timestamp (in seconds) of when the chat completion was created. Each chunk has the same timestamp.
    /// </summary>
    [JsonPropertyName("created")]
    [JsonRequired]
    public required long Created { get; init; }

    /// <summary>
    /// The model to generate the completion.
    /// </summary>
    [JsonPropertyName("model")]
    [JsonRequired]
    public required string Model { get; init; }

    /// <summary>
    /// Usage statistics for the completion request.
    /// </summary>
    [JsonPropertyName("usage")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public CompletionUsage? Usage { get; init; }

    /// <summary>
    /// The service tier used for processing the request. This field is only included if the service_tier parameter is specified in the request.
    /// </summary>
    [JsonPropertyName("service_tier")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public string? ServiceTier { get; init; }

    /// <summary>
    /// This fingerprint represents the backend configuration that the model runs with.
    /// Can be used in conjunction with the seed request parameter to understand when backend changes have been made that might impact determinism.
    /// </summary>
    [JsonPropertyName("system_fingerprint")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public string? SystemFingerprint { get; init; }
}

internal sealed record ChatCompletionChoiceChunk
{
    /// <summary>
    /// The index of the choice in the list of choices.
    /// </summary>
    [JsonPropertyName("index")]
    public required int Index { get; init; }

    /// <summary>
    /// The reason the model stopped generating tokens.
    /// This will be stop if the model hit a natural stop point or a provided stop sequence, length if the maximum number of tokens specified in the request was reached,
    /// content_filter if content was omitted due to a flag from our content filters, tool_calls if the model called a tool, or function_call (deprecated) if the model called a function.
    /// </summary>
    [JsonPropertyName("finish_reason")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public string? FinishReason { get; init; }

    [JsonPropertyName("delta")]
    public required ChatCompletionDelta Delta { get; init; }
}

internal sealed record ChatCompletionDelta
{
    /// <summary>
    /// The contents of the chunk message.
    /// </summary>
    [JsonPropertyName("content")]
    public string? Content { get; init; }

    /// <summary>
    /// The refusal message generated by the model.
    /// </summary>
    [JsonPropertyName("refusal")]
    public string? Refusal { get; init; }

    /// <summary>
    /// The role of the author of this message.
    /// </summary>
    [JsonPropertyName("role")]
    public string? Role { get; set; }

    /// <summary>
    /// Deprecated and replaced by tool_calls. The name and arguments of a function that should be called, as generated by the model.
    /// </summary>
    [JsonPropertyName("function_call")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public ChoiceMessageFunctionCall? FunctionCall { get; set; }

    [JsonPropertyName("tool_calls")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public IList<ChoiceMessageToolCall>? ToolCalls { get; set; }
}
