namespace adas_core.Authentication.Models;

/// <summary>
/// Represents a generic response in the Universal Chess Interface (UCI) protocol, encapsulating a payload of type <typeparamref name="T"/>.
/// </summary>
/// <typeparam name="T">The type of the response payload.</typeparam>
/// <!-- aidoc:v1 sig=edd025b -->
public class UciResponse<T>
{
    /// <summary>
    /// Initializes a new instance of the <see cref="UciResponse"/> class with default values.
    /// This protected parameterless constructor enables the <see cref="UciResponse"/> type to be instantiated by derived classes.
    /// </summary>
    /// <!-- aidoc:v1 sig=bc935a2 body=4448e1d -->
    protected UciResponse()
    {
    }

    /// <summary>
    /// Initializes a successful instance of the <see cref="UciResponse{T}"/> class, which wraps an entity as a response payload. The constructor assigns <paramref name="entity"/> to <see cref="UciResponse{T}.Data"/>, sets <see cref="UciResponse{T}.Success"/> to <c>true</c>, and clears <see cref="UciResponse{T}.Message"/> and <see cref="UciResponse{T}.Error"/>.
    /// </summary>
    /// <param name="entity">The payload to encapsulate in the response, stored in the <see cref="UciResponse{T}.Data"/> property.</param>
    /// <!-- aidoc:v1 sig=5205995 body=dd7f9e7 -->
    protected UciResponse(T entity)
    {
        Success = true;
        Data = entity;
        Message = null;
        Error = null;
    }

    public string? Error { get; set; }
    public DateTime Date { get; set; } = DateTime.Now;
    public bool Success { get; protected set; }
    public string? Message { get; protected set; }
    public T? Data { get; protected set; }


    /// <summary>
    /// Creates a successful <see cref="UciResponse{T}"/> wrapping the specified entity.
    /// </summary>
    /// <param name="entity">The entity to include in the response payload.</param>
    /// <returns>A <see cref="UciResponse{T}"/> containing the provided entity.</returns>
    /// <!-- aidoc:v1 sig=193e85b body=f1d7691 -->
    public static UciResponse<T> FromSuccess(T entity)
        {
            return new UciResponse<T>(entity);
        }


    /// <summary>
    /// Creates a <see cref="UciResponse{T}"/> representing an error state derived from the supplied exception, using the exception's type name (with the "Exception" suffix stripped) as the error code and its message as the error description.
    /// </summary>
    /// <param name="ex">The exception whose type name and message are used to populate the error response.</param>
    /// <returns>A <see cref="UciResponse{T}"/> containing the cleaned exception type name and the exception message as the error details.</returns>
    /// <!-- aidoc:v1 sig=f4afb5b body=80d56b7 -->
    public static UciResponse<T> FromError(Exception ex)
        {
            var error = ex.GetType().Name;
            var index = error.LastIndexOf("Exception", StringComparison.Ordinal);
            if (index > -1) error = error[..index];
            return FromError(error, ex.Message);
        }

    /// <summary>
    /// Creates a <see cref="UciResponse{T}"/> instance representing a failed operation, populating the error information and an optional descriptive message.
    /// </summary>
    /// <param name="error">The error code or identifier describing the failure.</param>
    /// <param name="message">An optional human-readable message providing additional context about the error.</param>
    /// <returns>A <see cref="UciResponse{T}"/> with <c>Success</c> set to <c>false</c>, the specified <paramref name="error"/>, and the optional <paramref name="message"/>.</returns>
    /// <!-- aidoc:v1 sig=43834ba body=b488e43 -->
    public static UciResponse<T> FromError(string error, string? message = null)
        {
            return new UciResponse<T>
            {
                Success = false,
                Error = error,
                Message = message
            };
        }
}