using ErsatzTV.Core.FFmpeg;
using ErsatzTV.Core.Interfaces.FFmpeg;
using FluentAssertions;
using Microsoft.Extensions.Logging;
using NSubstitute;
using NUnit.Framework;

namespace ErsatzTV.Core.Tests.FFmpeg;

[TestFixture]
public class HlsPlaylistFilterTests
{
    [SetUp]
    public void SetUp() =>
        _hlsPlaylistFilter = new HlsPlaylistFilter(
            Substitute.For<ITempFilePool>(),
            Substitute.For<ILogger<HlsPlaylistFilter>>()
        );

    private HlsPlaylistFilter _hlsPlaylistFilter;

    [Test]
    public void HlsPlaylistFilter_ShouldRewriteProgramDateTime()
    {
        var start = new DateTimeOffset(2021, 10, 9, 8, 0, 0, TimeSpan.FromHours(-5));
        string[] input = NormalizeLineEndings(
            @"#EXTM3U
#EXT-X-VERSION:6
#EXT-X-TARGETDURATION:4
#EXT-X-MEDIA-SEQUENCE:1137
#EXT-X-INDEPENDENT-SEGMENTS
#EXT-X-DISCONTINUITY
#EXTINF:4.000000,
#EXT-X-PROGRAM-DATE-TIME:2021-10-08T08:34:49.320-0500
live001137.ts
#EXTINF:4.000000,
#EXT-X-PROGRAM-DATE-TIME:2021-10-08T08:34:53.320-0500
live001138.ts
#EXTINF:4.000000,
#EXT-X-PROGRAM-DATE-TIME:2021-10-08T08:34:57.320-0500
live001139.ts").Split(Environment.NewLine);

        TrimPlaylistResult result = _hlsPlaylistFilter.TrimPlaylist(start, start.AddSeconds(-30), input);

        result.PlaylistStart.Should().Be(start);
        result.Sequence.Should().Be(1137);
        result.Playlist.Should().Be(
            NormalizeLineEndings(
                @"#EXTM3U
#EXT-X-VERSION:6
#EXT-X-TARGETDURATION:4
#EXT-X-MEDIA-SEQUENCE:1137
#EXT-X-DISCONTINUITY-SEQUENCE:1
#EXT-X-INDEPENDENT-SEGMENTS
#EXTINF:4.000000,
#EXT-X-PROGRAM-DATE-TIME:2021-10-09T08:00:00.000-0500
live001137.ts
#EXTINF:4.000000,
#EXT-X-PROGRAM-DATE-TIME:2021-10-09T08:00:04.000-0500
live001138.ts
#EXTINF:4.000000,
#EXT-X-PROGRAM-DATE-TIME:2021-10-09T08:00:08.000-0500
live001139.ts
"));
    }

    [Test]
    public void HlsPlaylistFilter_ShouldLimitSegments()
    {
        var start = new DateTimeOffset(2021, 10, 9, 8, 0, 0, TimeSpan.FromHours(-5));
        string[] input = NormalizeLineEndings(
            @"#EXTM3U
#EXT-X-VERSION:6
#EXT-X-TARGETDURATION:4
#EXT-X-MEDIA-SEQUENCE:1137
#EXT-X-INDEPENDENT-SEGMENTS
#EXT-X-DISCONTINUITY
#EXTINF:4.000000,
#EXT-X-PROGRAM-DATE-TIME:2021-10-08T08:34:49.320-0500
live001137.ts
#EXTINF:4.000000,
#EXT-X-PROGRAM-DATE-TIME:2021-10-08T08:34:53.320-0500
live001138.ts
#EXTINF:4.000000,
#EXT-X-PROGRAM-DATE-TIME:2021-10-08T08:34:57.320-0500
live001139.ts").Split(Environment.NewLine);

        TrimPlaylistResult result = _hlsPlaylistFilter.TrimPlaylist(start, start.AddSeconds(-30), input, 2);

        result.PlaylistStart.Should().Be(start);
        result.Sequence.Should().Be(1137);
        result.Playlist.Should().Be(
            NormalizeLineEndings(
                @"#EXTM3U
#EXT-X-VERSION:6
#EXT-X-TARGETDURATION:4
#EXT-X-MEDIA-SEQUENCE:1137
#EXT-X-DISCONTINUITY-SEQUENCE:1
#EXT-X-INDEPENDENT-SEGMENTS
#EXTINF:4.000000,
#EXT-X-PROGRAM-DATE-TIME:2021-10-09T08:00:00.000-0500
live001137.ts
#EXTINF:4.000000,
#EXT-X-PROGRAM-DATE-TIME:2021-10-09T08:00:04.000-0500
live001138.ts
"));
    }

    [Test]
    public void HlsPlaylistFilter_ShouldAddDiscontinuity()
    {
        var start = new DateTimeOffset(2021, 10, 9, 8, 0, 0, TimeSpan.FromHours(-5));
        string[] input = NormalizeLineEndings(
            @"#EXTM3U
#EXT-X-VERSION:6
#EXT-X-TARGETDURATION:4
#EXT-X-MEDIA-SEQUENCE:1137
#EXT-X-INDEPENDENT-SEGMENTS
#EXT-X-DISCONTINUITY
#EXTINF:4.000000,
#EXT-X-PROGRAM-DATE-TIME:2021-10-08T08:34:49.320-0500
live001137.ts
#EXTINF:4.000000,
#EXT-X-PROGRAM-DATE-TIME:2021-10-08T08:34:53.320-0500
live001138.ts
#EXTINF:4.000000,
#EXT-X-PROGRAM-DATE-TIME:2021-10-08T08:34:57.320-0500
live001139.ts").Split(Environment.NewLine);

        TrimPlaylistResult result = _hlsPlaylistFilter.TrimPlaylist(
            start,
            start.AddSeconds(-30),
            input,
            int.MaxValue,
            true);

        result.PlaylistStart.Should().Be(start);
        result.Sequence.Should().Be(1137);
        result.Playlist.Should().Be(
            NormalizeLineEndings(
                @"#EXTM3U
#EXT-X-VERSION:6
#EXT-X-TARGETDURATION:4
#EXT-X-MEDIA-SEQUENCE:1137
#EXT-X-DISCONTINUITY-SEQUENCE:1
#EXT-X-INDEPENDENT-SEGMENTS
#EXTINF:4.000000,
#EXT-X-PROGRAM-DATE-TIME:2021-10-09T08:00:00.000-0500
live001137.ts
#EXTINF:4.000000,
#EXT-X-PROGRAM-DATE-TIME:2021-10-09T08:00:04.000-0500
live001138.ts
#EXTINF:4.000000,
#EXT-X-PROGRAM-DATE-TIME:2021-10-09T08:00:08.000-0500
live001139.ts
#EXT-X-DISCONTINUITY
"));
    }

    [Test]
    public void HlsPlaylistFilter_ShouldFilterOldSegmentsBeyondMax()
    {
        var start = new DateTimeOffset(2021, 10, 9, 8, 0, 0, TimeSpan.FromHours(-5));
        string[] input = NormalizeLineEndings(
            @"#EXTM3U
#EXT-X-VERSION:6
#EXT-X-TARGETDURATION:4
#EXT-X-MEDIA-SEQUENCE:1137
#EXT-X-INDEPENDENT-SEGMENTS
#EXT-X-DISCONTINUITY
#EXTINF:4.000000,
#EXT-X-PROGRAM-DATE-TIME:2021-10-08T08:34:49.320-0500
live001137.ts
#EXTINF:4.000000,
#EXT-X-PROGRAM-DATE-TIME:2021-10-08T08:34:53.320-0500
live001138.ts
#EXTINF:4.000000,
#EXT-X-PROGRAM-DATE-TIME:2021-10-08T08:34:57.320-0500
live001139.ts").Split(Environment.NewLine);

        TrimPlaylistResult result = _hlsPlaylistFilter.TrimPlaylist(start, start.AddSeconds(6), input, 1);

        result.PlaylistStart.Should().Be(start.AddSeconds(8));
        result.Sequence.Should().Be(1139);
        result.Playlist.Should().Be(
            NormalizeLineEndings(
                @"#EXTM3U
#EXT-X-VERSION:6
#EXT-X-TARGETDURATION:4
#EXT-X-MEDIA-SEQUENCE:1139
#EXT-X-DISCONTINUITY-SEQUENCE:1
#EXT-X-INDEPENDENT-SEGMENTS
#EXTINF:4.000000,
#EXT-X-PROGRAM-DATE-TIME:2021-10-09T08:00:08.000-0500
live001139.ts
"));
    }

    [Test]
    public void HlsPlaylistFilter_ShouldFilterOldDiscontinuity()
    {
        var start = new DateTimeOffset(2021, 10, 9, 8, 0, 0, TimeSpan.FromHours(-5));
        string[] input = NormalizeLineEndings(
            @"#EXTM3U
#EXT-X-VERSION:6
#EXT-X-TARGETDURATION:4
#EXT-X-MEDIA-SEQUENCE:1137
#EXT-X-INDEPENDENT-SEGMENTS
#EXT-X-DISCONTINUITY
#EXTINF:4.000000,
#EXT-X-PROGRAM-DATE-TIME:2021-10-08T08:34:49.320-0500
live001137.ts
#EXT-X-DISCONTINUITY
#EXTINF:4.000000,
#EXT-X-PROGRAM-DATE-TIME:2021-10-08T08:34:53.320-0500
live001138.ts
#EXTINF:4.000000,
#EXT-X-PROGRAM-DATE-TIME:2021-10-08T08:34:57.320-0500
live001139.ts").Split(Environment.NewLine);

        TrimPlaylistResult result = _hlsPlaylistFilter.TrimPlaylist(start, start.AddSeconds(6), input);

        result.PlaylistStart.Should().Be(start);
        result.Sequence.Should().Be(1137);
        result.Playlist.Should().Be(
            NormalizeLineEndings(
                @"#EXTM3U
#EXT-X-VERSION:6
#EXT-X-TARGETDURATION:4
#EXT-X-MEDIA-SEQUENCE:1137
#EXT-X-DISCONTINUITY-SEQUENCE:1
#EXT-X-INDEPENDENT-SEGMENTS
#EXTINF:4.000000,
#EXT-X-PROGRAM-DATE-TIME:2021-10-09T08:00:00.000-0500
live001137.ts
#EXT-X-DISCONTINUITY
#EXTINF:4.000000,
#EXT-X-PROGRAM-DATE-TIME:2021-10-09T08:00:04.000-0500
live001138.ts
#EXTINF:4.000000,
#EXT-X-PROGRAM-DATE-TIME:2021-10-09T08:00:08.000-0500
live001139.ts
"));
    }

    [Test]
    public void HlsPlaylistFilter_Should_Increment_DiscontinuityCount()
    {
        var start = new DateTimeOffset(2022, 5, 25, 20, 8, 0, TimeSpan.FromHours(-5));
        string[] input = NormalizeLineEndings(
            @"#EXTM3U
#EXT-X-VERSION:6
#EXT-X-TARGETDURATION:4
#EXT-X-MEDIA-SEQUENCE:0
#EXT-X-DISCONTINUITY
#EXT-X-INDEPENDENT-SEGMENTS
#EXT-X-DISCONTINUITY
#EXTINF:4.004000,
#EXT-X-PROGRAM-DATE-TIME:2022-05-25T20:08:55.981-0500
live000000.ts
#EXTINF:4.004000,
#EXT-X-PROGRAM-DATE-TIME:2022-05-25T20:08:59.985-0500
live000001.ts
#EXTINF:4.004000,
#EXT-X-PROGRAM-DATE-TIME:2022-05-25T20:09:03.989-0500
live000002.ts
#EXTINF:4.004000,
#EXT-X-PROGRAM-DATE-TIME:2022-05-25T20:09:07.993-0500
live000003.ts
#EXTINF:4.004000,
#EXT-X-PROGRAM-DATE-TIME:2022-05-25T20:09:11.997-0500
live000004.ts
#EXTINF:4.004000,
#EXT-X-PROGRAM-DATE-TIME:2022-05-25T20:09:16.001-0500
live000005.ts
#EXTINF:4.004000,
#EXT-X-PROGRAM-DATE-TIME:2022-05-25T20:09:20.005-0500
live000006.ts
#EXTINF:4.004000,
#EXT-X-PROGRAM-DATE-TIME:2022-05-25T20:09:24.009-0500
live000007.ts
#EXTINF:3.970633,
#EXT-X-PROGRAM-DATE-TIME:2022-05-25T20:09:28.013-0500
live000008.ts
#EXTINF:4.004000,
#EXT-X-PROGRAM-DATE-TIME:2022-05-25T20:09:31.983-0500
live000009.ts
#EXTINF:4.004000,
#EXT-X-PROGRAM-DATE-TIME:2022-05-25T20:09:35.987-0500
live000010.ts
#EXTINF:4.004000,
#EXT-X-PROGRAM-DATE-TIME:2022-05-25T20:09:39.991-0500
live000011.ts
#EXTINF:4.004000,
#EXT-X-PROGRAM-DATE-TIME:2022-05-25T20:09:43.995-0500
live000012.ts
#EXTINF:4.004000,
#EXT-X-PROGRAM-DATE-TIME:2022-05-25T20:09:47.999-0500
live000013.ts
#EXTINF:4.004000,
#EXT-X-PROGRAM-DATE-TIME:2022-05-25T20:09:52.003-0500
live000014.ts
#EXTINF:4.004000,
#EXT-X-PROGRAM-DATE-TIME:2022-05-25T20:09:56.007-0500
live000015.ts
#EXTINF:3.970633,
#EXT-X-PROGRAM-DATE-TIME:2022-05-25T20:10:00.011-0500
live000016.ts
#EXTINF:4.004000,
#EXT-X-PROGRAM-DATE-TIME:2022-05-25T20:10:03.982-0500
live000017.ts
#EXTINF:4.004000,
#EXT-X-PROGRAM-DATE-TIME:2022-05-25T20:10:07.986-0500
live000018.ts
#EXTINF:4.004000,
#EXT-X-PROGRAM-DATE-TIME:2022-05-25T20:10:11.990-0500
live000019.ts
#EXTINF:4.004000,
#EXT-X-PROGRAM-DATE-TIME:2022-05-25T20:10:15.994-0500
live000020.ts
#EXTINF:4.004000,
#EXT-X-PROGRAM-DATE-TIME:2022-05-25T20:10:19.998-0500
live000021.ts
#EXTINF:4.004000,
#EXT-X-PROGRAM-DATE-TIME:2022-05-25T20:10:24.002-0500
live000022.ts
#EXTINF:4.004000,
#EXT-X-PROGRAM-DATE-TIME:2022-05-25T20:10:28.006-0500
live000023.ts
#EXTINF:4.004000,
#EXT-X-PROGRAM-DATE-TIME:2022-05-25T20:10:32.010-0500
live000024.ts
#EXTINF:3.970633,
#EXT-X-PROGRAM-DATE-TIME:2022-05-25T20:10:36.014-0500
live000025.ts
#EXTINF:4.004000,
#EXT-X-PROGRAM-DATE-TIME:2022-05-25T20:10:39.985-0500
live000026.ts
#EXTINF:4.004000,
#EXT-X-PROGRAM-DATE-TIME:2022-05-25T20:10:43.989-0500
live000027.ts
#EXTINF:4.004000,
#EXT-X-PROGRAM-DATE-TIME:2022-05-25T20:10:47.993-0500
live000028.ts
#EXTINF:4.004000,
#EXT-X-PROGRAM-DATE-TIME:2022-05-25T20:10:51.997-0500
live000029.ts
#EXTINF:4.004000,
#EXT-X-PROGRAM-DATE-TIME:2022-05-25T20:10:56.001-0500
live000030.ts
#EXTINF:4.004000,
#EXT-X-PROGRAM-DATE-TIME:2022-05-25T20:11:00.005-0500
live000031.ts
#EXTINF:4.004000,
#EXT-X-PROGRAM-DATE-TIME:2022-05-25T20:11:04.009-0500
live000032.ts
#EXTINF:3.970633,
#EXT-X-PROGRAM-DATE-TIME:2022-05-25T20:11:08.013-0500
live000033.ts
#EXTINF:4.004000,
#EXT-X-PROGRAM-DATE-TIME:2022-05-25T20:11:11.983-0500
live000034.ts
#EXTINF:4.004000,
#EXT-X-PROGRAM-DATE-TIME:2022-05-25T20:11:15.987-0500
live000035.ts
#EXTINF:4.004000,
#EXT-X-PROGRAM-DATE-TIME:2022-05-25T20:11:19.991-0500
live000036.ts
#EXTINF:4.004000,
#EXT-X-PROGRAM-DATE-TIME:2022-05-25T20:11:23.995-0500
live000037.ts
#EXTINF:4.004000,
#EXT-X-PROGRAM-DATE-TIME:2022-05-25T20:11:27.999-0500
live000038.ts
#EXTINF:4.004000,
#EXT-X-PROGRAM-DATE-TIME:2022-05-25T20:11:32.003-0500
live000039.ts
#EXTINF:4.004000,
#EXT-X-PROGRAM-DATE-TIME:2022-05-25T20:11:36.007-0500
live000040.ts
#EXTINF:3.970633,
#EXT-X-PROGRAM-DATE-TIME:2022-05-25T20:11:40.011-0500
live000041.ts
#EXTINF:4.004000,
#EXT-X-PROGRAM-DATE-TIME:2022-05-25T20:11:43.982-0500
live000042.ts
#EXTINF:4.004000,
#EXT-X-PROGRAM-DATE-TIME:2022-05-25T20:11:47.986-0500
live000043.ts
#EXTINF:4.004000,
#EXT-X-PROGRAM-DATE-TIME:2022-05-25T20:11:51.990-0500
live000044.ts
#EXTINF:4.004000,
#EXT-X-PROGRAM-DATE-TIME:2022-05-25T20:11:55.994-0500
live000045.ts
#EXTINF:4.004000,
#EXT-X-PROGRAM-DATE-TIME:2022-05-25T20:11:59.998-0500
live000046.ts
#EXTINF:4.004000,
#EXT-X-PROGRAM-DATE-TIME:2022-05-25T20:12:04.002-0500
live000047.ts
#EXTINF:4.004000,
#EXT-X-PROGRAM-DATE-TIME:2022-05-25T20:12:08.006-0500
live000048.ts
#EXTINF:4.004000,
#EXT-X-PROGRAM-DATE-TIME:2022-05-25T20:12:12.010-0500
live000049.ts
#EXTINF:3.970633,
#EXT-X-PROGRAM-DATE-TIME:2022-05-25T20:12:16.014-0500
live000050.ts
#EXTINF:4.004000,
#EXT-X-PROGRAM-DATE-TIME:2022-05-25T20:12:19.985-0500
live000051.ts
#EXTINF:0.433767,
#EXT-X-PROGRAM-DATE-TIME:2022-05-25T20:12:23.989-0500
live000052.ts
#EXT-X-DISCONTINUITY
#EXTINF:4.000000,
#EXT-X-PROGRAM-DATE-TIME:2022-05-25T20:11:30.007-0500
live000053.ts
#EXTINF:4.000000,
#EXT-X-PROGRAM-DATE-TIME:2022-05-25T20:11:34.007-0500
live000054.ts
#EXTINF:4.000000,
#EXT-X-PROGRAM-DATE-TIME:2022-05-25T20:11:38.007-0500
live000055.ts
#EXTINF:4.000000,
#EXT-X-PROGRAM-DATE-TIME:2022-05-25T20:11:42.007-0500
live000056.ts
#EXTINF:4.000000,
#EXT-X-PROGRAM-DATE-TIME:2022-05-25T20:11:46.007-0500
live000057.ts
#EXTINF:4.000000,
#EXT-X-PROGRAM-DATE-TIME:2022-05-25T20:11:50.007-0500
live000058.ts
#EXTINF:4.000000,
#EXT-X-PROGRAM-DATE-TIME:2022-05-25T20:11:54.007-0500
live000059.ts
#EXTINF:4.000000,
#EXT-X-PROGRAM-DATE-TIME:2022-05-25T20:11:58.007-0500
live000060.ts
#EXTINF:4.000000,
#EXT-X-PROGRAM-DATE-TIME:2022-05-25T20:12:02.007-0500
live000061.ts
#EXTINF:4.000000,
#EXT-X-PROGRAM-DATE-TIME:2022-05-25T20:12:06.007-0500
live000062.ts
#EXTINF:4.000000,
#EXT-X-PROGRAM-DATE-TIME:2022-05-25T20:12:10.007-0500
live000063.ts
#EXTINF:4.000000,
#EXT-X-PROGRAM-DATE-TIME:2022-05-25T20:12:14.007-0500
live000064.ts
#EXTINF:4.000000,
#EXT-X-PROGRAM-DATE-TIME:2022-05-25T20:12:18.007-0500
live000065.ts
#EXTINF:4.000000,
#EXT-X-PROGRAM-DATE-TIME:2022-05-25T20:12:22.007-0500
live000066.ts
#EXTINF:4.000000,
#EXT-X-PROGRAM-DATE-TIME:2022-05-25T20:12:26.007-0500
live000067.ts
#EXTINF:4.000000,
#EXT-X-PROGRAM-DATE-TIME:2022-05-25T20:12:30.007-0500
live000068.ts
#EXTINF:4.000000,
#EXT-X-PROGRAM-DATE-TIME:2022-05-25T20:12:34.007-0500
live000069.ts
#EXTINF:4.000000,
#EXT-X-PROGRAM-DATE-TIME:2022-05-25T20:12:38.007-0500
live000070.ts
#EXTINF:4.000000,
#EXT-X-PROGRAM-DATE-TIME:2022-05-25T20:12:42.007-0500
live000071.ts
#EXTINF:4.000000,
#EXT-X-PROGRAM-DATE-TIME:2022-05-25T20:12:46.007-0500
live000072.ts
#EXTINF:4.000000,
#EXT-X-PROGRAM-DATE-TIME:2022-05-25T20:12:50.007-0500
live000073.ts
#EXTINF:4.000000,
#EXT-X-PROGRAM-DATE-TIME:2022-05-25T20:12:54.007-0500
live000074.ts
#EXTINF:4.000000,
#EXT-X-PROGRAM-DATE-TIME:2022-05-25T20:12:58.007-0500
live000075.ts
#EXTINF:4.000000,
#EXT-X-PROGRAM-DATE-TIME:2022-05-25T20:13:02.007-0500
live000076.ts
#EXTINF:4.000000,
#EXT-X-PROGRAM-DATE-TIME:2022-05-25T20:13:06.007-0500
live000077.ts
#EXTINF:4.000000,
#EXT-X-PROGRAM-DATE-TIME:2022-05-25T20:13:10.007-0500
live000078.ts
#EXTINF:4.000000,
#EXT-X-PROGRAM-DATE-TIME:2022-05-25T20:13:14.007-0500
live000079.ts
#EXTINF:4.000000,
#EXT-X-PROGRAM-DATE-TIME:2022-05-25T20:13:18.007-0500
live000080.ts
#EXTINF:4.000000,
#EXT-X-PROGRAM-DATE-TIME:2022-05-25T20:13:22.007-0500
live000081.ts
#EXTINF:4.000000,
#EXT-X-PROGRAM-DATE-TIME:2022-05-25T20:13:26.007-0500
live000082.ts").Split(Environment.NewLine);

        TrimPlaylistResult result = _hlsPlaylistFilter.TrimPlaylist(start, start.AddSeconds(220), input);

        // result.PlaylistStart.Should().Be(start);
        result.Sequence.Should().Be(56);
        result.Playlist.Should().Be(
            NormalizeLineEndings(
                @"#EXTM3U
#EXT-X-VERSION:6
#EXT-X-TARGETDURATION:4
#EXT-X-MEDIA-SEQUENCE:56
#EXT-X-DISCONTINUITY-SEQUENCE:2
#EXT-X-INDEPENDENT-SEGMENTS
#EXTINF:4.000000,
#EXT-X-PROGRAM-DATE-TIME:2022-05-25T20:11:40.441-0500
live000056.ts
#EXTINF:4.000000,
#EXT-X-PROGRAM-DATE-TIME:2022-05-25T20:11:44.441-0500
live000057.ts
#EXTINF:4.000000,
#EXT-X-PROGRAM-DATE-TIME:2022-05-25T20:11:48.441-0500
live000058.ts
#EXTINF:4.000000,
#EXT-X-PROGRAM-DATE-TIME:2022-05-25T20:11:52.441-0500
live000059.ts
#EXTINF:4.000000,
#EXT-X-PROGRAM-DATE-TIME:2022-05-25T20:11:56.441-0500
live000060.ts
#EXTINF:4.000000,
#EXT-X-PROGRAM-DATE-TIME:2022-05-25T20:12:00.441-0500
live000061.ts
#EXTINF:4.000000,
#EXT-X-PROGRAM-DATE-TIME:2022-05-25T20:12:04.441-0500
live000062.ts
#EXTINF:4.000000,
#EXT-X-PROGRAM-DATE-TIME:2022-05-25T20:12:08.441-0500
live000063.ts
#EXTINF:4.000000,
#EXT-X-PROGRAM-DATE-TIME:2022-05-25T20:12:12.441-0500
live000064.ts
#EXTINF:4.000000,
#EXT-X-PROGRAM-DATE-TIME:2022-05-25T20:12:16.441-0500
live000065.ts
"));
    }

    private static string NormalizeLineEndings(string str) =>
        str
            .Replace("\r\n", "\n")
            .Replace("\r", "\n")
            .Replace("\n", Environment.NewLine);
}
