using TeleWave.Domain.Broadcast;
using Xunit;

namespace TeleWave.Domain.Tests.Broadcast;

public class ChannelTests
{
    private static readonly DateTimeOffset Epoch = new(2026, 1, 1, 0, 0, 0, TimeSpan.Zero);

    private static Channel NewChannel() => Channel.Create("News", "news", Epoch);

    [Fact]
    public void Create_SetsDefaults()
    {
        var channel = NewChannel();

        Assert.NotEqual(Guid.Empty, channel.Id);
        Assert.Equal("News", channel.Name);
        Assert.Equal("news", channel.Slug);
        Assert.True(channel.IsEnabled);
        Assert.Equal(Epoch, channel.EpochUtc);
        Assert.Equal(Channel.DefaultUtcOffsetMinutes, channel.UtcOffsetMinutes);
        Assert.Equal(Channel.DefaultDayStartTime, channel.DayStartTime);
    }

    [Fact]
    public void UpdateSettings_ChangesFields()
    {
        var channel = NewChannel();
        var filler = Guid.NewGuid();

        channel.UpdateSettings("N2", false, filler);

        Assert.Equal("N2", channel.Name);
        Assert.False(channel.IsEnabled);
        Assert.Equal(filler, channel.FillerAssetId);
    }

    [Theory]
    [InlineData(-1.0, 2.0, 0.0, 1.0)]
    [InlineData(0.4, 0.25, 0.4, 0.25)]
    public void UpdateViewerSettings_ClampsStrengths(
        double opacity,
        double filter,
        double expectedOpacity,
        double expectedFilter
    )
    {
        var channel = NewChannel();
        var logo = Guid.NewGuid();

        channel.UpdateViewerSettings(logo, LogoCorner.BottomRight, opacity, true, filter);

        Assert.Equal(logo, channel.LogoImageId);
        Assert.Equal(LogoCorner.BottomRight, channel.LogoCorner);
        Assert.Equal(expectedOpacity, channel.LogoOpacity);
        Assert.True(channel.ShowClock);
        Assert.Equal(expectedFilter, channel.AnalogFilterStrength);
    }

    [Fact]
    public void NewChannel_HasViewerOverlaysOff()
    {
        // Канал без логотипа, часов и шума — законная конфигурация, а не недонастроенная.
        var channel = NewChannel();

        Assert.Null(channel.LogoImageId);
        Assert.False(channel.ShowClock);
        Assert.Equal(0.0, channel.AnalogFilterStrength);
    }

    [Fact]
    public void UpdateTimeSettings_ClampsOffsetAndDropsNonPositiveNumber()
    {
        var channel = NewChannel();

        channel.UpdateTimeSettings(0, 99 * 60, new TimeOnly(5, 0));

        // Номер 0 — не номер; смещение за пределами суток оторвало бы сетку от календаря.
        Assert.Null(channel.Number);
        Assert.Equal(14 * 60, channel.UtcOffsetMinutes);
        Assert.Equal(new TimeOnly(5, 0), channel.DayStartTime);
    }

    [Fact]
    public void SetTemplate_LinksAndUnlinks()
    {
        var channel = NewChannel();
        var templateId = Guid.NewGuid();

        channel.SetTemplate(templateId);
        Assert.Equal(templateId, channel.TemplateId);

        channel.SetTemplate(null);
        Assert.Null(channel.TemplateId);
    }
}
