using TeleWave.Domain.Media;
using Xunit;

namespace TeleWave.Domain.Tests.Media;

public class MediaAssetTests
{
    [Fact]
    public void Register_CreatesPendingAsset_WithNormalizedExtension()
    {
        var asset = MediaAsset.Register("Simpsons S05E01.MKV", ".MKV", MediaSource.Upload);

        Assert.Equal(MediaAssetStatus.Pending, asset.Status);
        Assert.Equal(".mkv", asset.OriginalExtension);
        Assert.Equal("Simpsons S05E01.MKV", asset.OriginalFileName);
        Assert.Equal(MediaSource.Upload, asset.Source);
        Assert.NotEqual(Guid.Empty, asset.Id);
    }

    [Fact]
    public void MarkProcessing_SetsProcessingAndClearsError()
    {
        var asset = MediaAsset.Register("a.mp4", ".mp4", MediaSource.Inbox);
        asset.MarkFailed("boom");

        asset.MarkProcessing();

        Assert.Equal(MediaAssetStatus.Processing, asset.Status);
        Assert.Null(asset.ErrorMessage);
    }

    [Fact]
    public void MarkReady_StoresSegmentationMetadata()
    {
        var asset = MediaAsset.Register("a.mp4", ".mp4", MediaSource.Upload);

        asset.MarkReady(
            new MediaReadyInfo(
                TimeSpan.FromSeconds(120),
                SegmentSeconds: 2,
                SegmentCount: 60,
                Width: 1920,
                Height: 1080,
                VideoCodec: "h264",
                AudioCodec: "aac",
                RelativePath: "assets/abc"
            )
        );

        Assert.Equal(MediaAssetStatus.Ready, asset.Status);
        Assert.Equal(TimeSpan.FromSeconds(120), asset.Duration);
        Assert.Equal(2, asset.SegmentSeconds);
        Assert.Equal(60, asset.SegmentCount);
        Assert.Equal(1920, asset.Width);
        Assert.Equal(1080, asset.Height);
        Assert.Equal("assets/abc", asset.RelativePath);
        Assert.Null(asset.ErrorMessage);
    }

    [Fact]
    public void MarkProcessing_RecordsStart_AndMarkReady_ComputesProcessingDuration()
    {
        var asset = MediaAsset.Register("a.mp4", ".mp4", MediaSource.Upload);

        asset.MarkProcessing();
        Assert.NotNull(asset.ProcessingStartedAt);
        Assert.Null(asset.ProcessingDuration);

        asset.MarkReady(
            new MediaReadyInfo(
                TimeSpan.FromSeconds(120),
                2,
                60,
                1920,
                1080,
                "h264",
                "aac",
                "assets/abc"
            )
        );

        Assert.NotNull(asset.ProcessingDuration);
        Assert.True(asset.ProcessingDuration >= TimeSpan.Zero);
    }

    [Fact]
    public void MarkReady_WithoutProcessingStart_LeavesDurationNull()
    {
        var asset = MediaAsset.Register("a.mp4", ".mp4", MediaSource.Upload);

        asset.MarkReady(
            new MediaReadyInfo(
                TimeSpan.FromSeconds(120),
                2,
                60,
                1920,
                1080,
                "h264",
                "aac",
                "assets/abc"
            )
        );

        Assert.Null(asset.ProcessingDuration);
    }

    [Fact]
    public void MarkFailed_StoresError()
    {
        var asset = MediaAsset.Register("a.mp4", ".mp4", MediaSource.Upload);

        asset.MarkFailed("ffmpeg exited 1");

        Assert.Equal(MediaAssetStatus.Failed, asset.Status);
        Assert.Equal("ffmpeg exited 1", asset.ErrorMessage);
    }

    [Fact]
    public void ResetToPending_FromProcessing_ReturnsToQueue()
    {
        var asset = MediaAsset.Register("a.mp4", ".mp4", MediaSource.Upload);
        asset.MarkProcessing();

        asset.ResetToPending();

        Assert.Equal(MediaAssetStatus.Pending, asset.Status);
    }
}
