using System.Globalization;
using System.Text.Json;
using System.Text.Json.Serialization;

namespace ROLAC.API.Json;

/// <summary>
/// Reads <see cref="DateOnly"/> from either "yyyy-MM-dd" or any ISO 8601 date-time
/// (the date portion is taken). Writes as "yyyy-MM-dd". Lets JS clients send a Date
/// without first formatting it.
/// </summary>
public sealed class TolerantDateOnlyConverter : JsonConverter<DateOnly>
{
    private const string Format = "yyyy-MM-dd";

    public override DateOnly Read(ref Utf8JsonReader reader, Type typeToConvert, JsonSerializerOptions options)
    {
        var s = reader.GetString();
        if (string.IsNullOrEmpty(s))
            throw new JsonException("Expected a date string for DateOnly.");

        if (DateOnly.TryParseExact(s, Format, CultureInfo.InvariantCulture, DateTimeStyles.None, out var d))
            return d;

        if (DateTimeOffset.TryParse(s, CultureInfo.InvariantCulture, DateTimeStyles.None, out var dto))
            return DateOnly.FromDateTime(dto.DateTime);

        throw new JsonException($"Unable to parse '{s}' as DateOnly.");
    }

    public override void Write(Utf8JsonWriter writer, DateOnly value, JsonSerializerOptions options)
        => writer.WriteStringValue(value.ToString(Format, CultureInfo.InvariantCulture));
}
