using DeepDrftPublic.Client.Common;

namespace DeepDrftTests;

/// <summary>
/// Unit tests for <see cref="SeoUrls"/> — the absolute-URL composition shared by the SeoModel factories
/// and SeoHead (Phase 22). Origin always comes from config (never a browser API), so these pin the
/// slash-join, the cover-vs-default fallback (C6/AC4), and the ISO-8601 duration edge cases.
/// </summary>
[TestFixture]
public class SeoUrlsTests
{
    private static readonly SeoOptions Options = new()
    {
        BaseUrl = "https://deepdrft.com",
        DefaultImageUrl = "/img/og-default.png",
    };

    [TestCase("/cuts/key", "https://deepdrft.com/cuts/key")]
    [TestCase("cuts/key", "https://deepdrft.com/cuts/key")]
    [TestCase("/", "https://deepdrft.com/")]
    [TestCase("", "https://deepdrft.com")]
    public void Absolute_JoinsOriginAndPath_WithoutDoublingOrDroppingSlash(string path, string expected)
    {
        Assert.That(SeoUrls.Absolute(Options, path), Is.EqualTo(expected));
    }

    [Test]
    public void Absolute_TrimsTrailingSlashOnBaseUrl()
    {
        var withSlash = Options with { BaseUrl = "https://deepdrft.com/" };
        Assert.That(SeoUrls.Absolute(withSlash, "/cuts"), Is.EqualTo("https://deepdrft.com/cuts"));
    }

    [Test]
    public void CoverOrDefault_WithCover_BuildsEscapedImageRoute()
    {
        Assert.That(SeoUrls.CoverOrDefault(Options, "my cover.jpg"),
            Is.EqualTo("https://deepdrft.com/api/image/my%20cover.jpg"));
    }

    [TestCase(null)]
    [TestCase("")]
    [TestCase("   ")]
    public void CoverOrDefault_WithoutCover_FallsBackToDefaultImage(string? image)
    {
        Assert.That(SeoUrls.CoverOrDefault(Options, image),
            Is.EqualTo("https://deepdrft.com/img/og-default.png"));
    }

    [TestCase(30.0, "PT30S")]
    [TestCase(90.0, "PT1M30S")]
    [TestCase(3723.0, "PT1H2M3S")]
    public void IsoDuration_PositiveSeconds_RendersIso8601(double seconds, string expected)
    {
        Assert.That(SeoUrls.IsoDuration(seconds), Is.EqualTo(expected));
    }

    [TestCase(null)]
    [TestCase(0.0)]
    [TestCase(-5.0)]
    [TestCase(double.NaN)]
    [TestCase(double.PositiveInfinity)]
    public void IsoDuration_NonPositiveOrNonFinite_ReturnsNull(double? seconds)
    {
        Assert.That(SeoUrls.IsoDuration(seconds), Is.Null);
    }
}
