namespace DeepDrftPublic.Client.Common;

/// <summary>
/// Absolute-URL composition for SEO tags (Phase 22). Canonical / <c>og:url</c> / <c>og:image</c> origins
/// all come from <see cref="SeoOptions.BaseUrl"/> (config), never from a browser API — there is no
/// <c>window.location</c> during server prerender and the request host is unreliable behind nginx
/// (§5, OQ1). Shared by the <c>SeoModel</c> factories (which absolutise JSON-LD <c>url</c>/<c>image</c>)
/// and <c>SeoHead</c> (which absolutises the meta/OG tags) so the rule lives in exactly one place.
/// </summary>
public static class SeoUrls
{
    /// <summary>BaseUrl + a site-relative path. Both sides are trimmed so the join never doubles or drops the slash.</summary>
    public static string Absolute(SeoOptions options, string path)
    {
        var origin = options.BaseUrl.TrimEnd('/');
        if (string.IsNullOrEmpty(path)) return origin;
        return $"{origin}/{path.TrimStart('/')}";
    }

    /// <summary>
    /// Absolute URL of a release/track cover from its FileDatabase <c>ImagePath</c>, via the public image
    /// route (<c>api/image/{escaped}</c>). Returns the configured default share image when no cover exists
    /// (C6/AC4 — a default guarantees <c>og:image</c> presence).
    /// </summary>
    public static string CoverOrDefault(SeoOptions options, string? imagePath)
    {
        if (string.IsNullOrWhiteSpace(imagePath))
            return Absolute(options, options.DefaultImageUrl);

        return Absolute(options, $"api/image/{Uri.EscapeDataString(imagePath)}");
    }

    /// <summary>
    /// ISO-8601 duration (e.g. <c>PT1H2M3S</c>) from a seconds value, for JSON-LD <c>duration</c> and the
    /// <c>music:duration</c> OG tag. Null / non-finite / non-positive input yields null (omit the tag).
    /// </summary>
    public static string? IsoDuration(double? seconds)
    {
        if (seconds is null || double.IsNaN(seconds.Value) || double.IsInfinity(seconds.Value) || seconds.Value <= 0)
            return null;

        return System.Xml.XmlConvert.ToString(TimeSpan.FromSeconds(seconds.Value));
    }
}
