using System.Text.Json.Serialization;

namespace Web.Api.Common;

public sealed class ApiResponse
{
    [JsonPropertyName("success")]
    public bool Success { get; init; }

    [JsonPropertyName("data")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public object? Data { get; init; }

    [JsonPropertyName("status")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingDefault)]
    public int Status { get; init; }

    [JsonPropertyName("message")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public string? Message { get; init; }

    [JsonPropertyName("errors")]
    [JsonIgnore(Condition = JsonIgnoreCondition.WhenWritingNull)]
    public object? Errors { get; init; }

    public static IResult Ok(object? data = null)
    {
        string? message = null;

        if (data is not null)
        {
            var type = data.GetType();
            var msgProp = type.GetProperty("message", System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance | System.Reflection.BindingFlags.IgnoreCase);

            if (msgProp is not null && msgProp.PropertyType == typeof(string))
            {
                message = msgProp.GetValue(data) as string;

                // message 외 다른 속성이 없으면 data를 null로 설정
                var otherProps = type.GetProperties(System.Reflection.BindingFlags.Public | System.Reflection.BindingFlags.Instance).Where(p => !string.Equals(p.Name, "message", StringComparison.OrdinalIgnoreCase));
                if (!otherProps.Any())
                {
                    data = null;
                }
            }
        }

        return Results.Ok(new ApiResponse
        {
            Success = true,
            Message = message,
            Data = data
        });
    }

    public static IResult Created(object? data = null)
    {
        return Results.Json(new ApiResponse
        {
            Success = true,
            Data = data
        }, statusCode: StatusCodes.Status201Created);
    }

    public static IResult Fail(int status, string message, object? errors = null)
    {
        return Results.Json(new ApiResponse
        {
            Success = false,
            Status = status,
            Message = message,
            Errors = errors
        }, statusCode: status);
    }
}