namespace ZB.MOM.WW.MxGateway.Server.Dashboard.Components;

public static class DashboardDisplay
{
    /// <summary>
    /// Formats a nullable date and time value for display.
    /// </summary>
    /// <param name="value">The date and time to format.</param>
    /// <returns>Formatted date and time string or "-" if null.</returns>
    public static string DateTime(DateTimeOffset? value)
    {
        return value.HasValue
            ? value.Value.UtcDateTime.ToString("yyyy-MM-dd HH:mm:ss 'UTC'", System.Globalization.CultureInfo.InvariantCulture)
            : "-";
    }

    /// <summary>
    /// Formats a time span duration for display.
    /// </summary>
    /// <param name="value">The duration to format.</param>
    /// <returns>Formatted duration string.</returns>
    public static string Duration(TimeSpan value)
    {
        return value.TotalDays >= 1
            ? value.ToString(@"d\.hh\:mm\:ss", System.Globalization.CultureInfo.InvariantCulture)
            : value.ToString(@"hh\:mm\:ss", System.Globalization.CultureInfo.InvariantCulture);
    }

    /// <summary>
    /// Formats a nullable text value for display.
    /// </summary>
    /// <param name="value">The text to format.</param>
    /// <returns>Formatted text or "-" if null or empty.</returns>
    public static string Text(string? value)
    {
        return string.IsNullOrWhiteSpace(value) ? "-" : value;
    }

    /// <summary>
    /// Formats a nullable text value for display, shortened to a maximum length.
    /// </summary>
    /// <remarks>
    /// For table cells bound to text the gateway does not control — fault messages, COM
    /// exception text, SQL errors. One multi-line exception otherwise makes a single row
    /// several times taller than its neighbours. Call sites keep the full text reachable
    /// on the element's <c>title</c> and on the row's detail page.
    /// </remarks>
    /// <param name="value">The text to format.</param>
    /// <param name="maxLength">Maximum characters to render before the ellipsis.</param>
    /// <returns>Formatted text, ellipsized when longer than <paramref name="maxLength"/>, or "-" if null or empty.</returns>
    public static string Abbreviate(string? value, int maxLength = 80)
    {
        if (string.IsNullOrWhiteSpace(value))
        {
            return "-";
        }

        // Length-checked, never a bare range slice: a value shorter than maxLength
        // would throw and take the whole page render down with it.
        return value.Length <= maxLength
            ? value
            : string.Concat(value.AsSpan(0, maxLength).TrimEnd(), "…");
    }

    /// <summary>
    /// Formats a long count value for display with thousands separator.
    /// </summary>
    /// <param name="value">The count to format.</param>
    /// <returns>Formatted count string.</returns>
    public static string Count(long value)
    {
        return value.ToString("N0", System.Globalization.CultureInfo.InvariantCulture);
    }

    /// <summary>
    /// Retrieves a metric value from a snapshot by name and optional dimension.
    /// </summary>
    /// <param name="snapshot">Dashboard snapshot.</param>
    /// <param name="name">Metric name.</param>
    /// <param name="dimension">Optional metric dimension.</param>
    /// <returns>Metric value or zero if not found.</returns>
    public static long MetricValue(DashboardSnapshot snapshot, string name, string? dimension = null)
    {
        return snapshot.Metrics.FirstOrDefault(metric =>
            string.Equals(metric.Name, name, StringComparison.Ordinal)
            && string.Equals(metric.Dimension, dimension, StringComparison.Ordinal))?.Value ?? 0;
    }
}
