using System.Globalization;
using System.Text.Json.Serialization;
using Semver;
using StabilityMatrix.Core.Converters.Json;
using StabilityMatrix.Core.Extensions;

namespace StabilityMatrix.Core.Models.Update;

public record UpdateInfo
{
    [JsonConverter(typeof(SemVersionJsonConverter))]
    public required SemVersion Version { get; init; }

    public required DateTimeOffset ReleaseDate { get; init; }

    public UpdateChannel Channel { get; init; }

    public UpdateType Type { get; init; }

    public required Uri Url { get; init; }

    public required Uri Changelog { get; init; }

    /// <summary>
    /// Blake3 hash of the file
    /// </summary>
    public required string HashBlake3 { get; init; }

    /// <summary>
    /// ED25519 signature of the semicolon seperated string:
    /// "version + releaseDate + channel + type + url + changelog + hash_blake3"
    /// verifiable using our stored public key
    /// </summary>
    public required string Signature { get; init; }

    /// <summary>
    /// Data for use in signature verification.
    /// Semicolon separated string of fields:
    /// "version, releaseDate, channel, type, url, changelog, hashBlake3"
    /// </summary>
    public string GetSignedData()
    {
        var channel = Channel.GetStringValue().ToLowerInvariant();
        var date = FormatDateTimeOffsetInvariant(ReleaseDate);
        return $"{Version};{date};{channel};" + $"{(int)Type};{Url};{Changelog};" + $"{HashBlake3}";
    }

    /// <summary>
    /// Format a DatetimeOffset to a culture invariant string for use in signature verification.
    /// </summary>
    private static string FormatDateTimeOffsetInvariant(DateTimeOffset dateTimeOffset)
    {
        return dateTimeOffset.ToString(
            @"yyyy-MM-ddTHH\:mm\:ss.ffffffzzz",
            CultureInfo.InvariantCulture
        );
    }
}
