namespace ScadaLink.CentralUI.Components;

/// <summary>
/// Converts <c>&lt;input type="datetime-local"&gt;</c> values — which are always
/// expressed in the user's <i>browser-local</i> time zone — into UTC
/// <see cref="DateTimeOffset"/>s for querying.
/// <para>
/// CLAUDE.md mandates UTC throughout the system, but a <c>datetime-local</c>
/// value carries no offset, so it must be <i>converted</i> to UTC, not relabelled
/// as UTC. Relabelling (the CentralUI-008 bug) shifts every query window by the
/// user's offset for any non-UTC browser.
/// </para>
/// </summary>
public static class BrowserTime
{
    /// <summary>
    /// Converts a browser-local <paramref name="localValue"/> to UTC using the
    /// browser's <c>Date.getTimezoneOffset()</c> result.
    /// </summary>
    /// <param name="localValue">
    /// The wall-clock value from a <c>datetime-local</c> input, or <c>null</c>.
    /// </param>
    /// <param name="browserUtcOffsetMinutes">
    /// The value of JavaScript <c>new Date().getTimezoneOffset()</c>: the number
    /// of minutes that, <b>added</b> to local time, yields UTC. It is positive
    /// for time zones behind UTC (e.g. +300 for UTC-5) and negative for zones
    /// ahead (e.g. -120 for UTC+2).
    /// </param>
    /// <returns>The equivalent instant in UTC, or <c>null</c> when the input is null.</returns>
    public static DateTimeOffset? LocalInputToUtc(DateTime? localValue, int browserUtcOffsetMinutes)
    {
        if (localValue is not { } local)
            return null;

        // getTimezoneOffset() is defined as (UTC - local) in minutes, so
        // UTC = local + offset.
        var utc = DateTime.SpecifyKind(local, DateTimeKind.Unspecified)
            .AddMinutes(browserUtcOffsetMinutes);
        return new DateTimeOffset(utc, TimeSpan.Zero);
    }
}
