using TeleWave.Application.Media.MovieImport;
using Xunit;

namespace TeleWave.Application.Tests.Media;

/// <summary>
/// Валидаторы разбора фильмов. Проверяют вход до хендлера, поэтому важны обе стороны: пропустить
/// нормальную строку и не пропустить ту, что уронила бы разбор или ушла бы во внешний источник.
/// </summary>
public class MovieImportValidatorTests
{
    private static MovieImportItem FromManual(string? title = "Гладиатор") =>
        new("Gladiator.2000.mkv", null, title!, 2000, "98");

    private static MovieImportItem Uploaded() => new(null, Guid.NewGuid(), "Гладиатор", 2000, null);

    [Fact]
    public void Match_AcceptsNormalBatch()
    {
        var command = new MatchMoviesQuery(["a.mkv", "b.mkv"], "tmdb");

        Assert.True(new MatchMoviesQueryValidator().Validate(command).IsValid);
    }

    [Theory]
    [InlineData(0)] // пустой список разбирать нечего
    [InlineData(201)] // каждая строка — запрос во внешний источник, и пачка ограничена
    public void Match_RejectsBadBatchSize(int count)
    {
        var names = Enumerable.Range(0, count).Select(i => $"{i}.mkv").ToList();

        Assert.False(
            new MatchMoviesQueryValidator().Validate(new MatchMoviesQuery(names, "tmdb")).IsValid
        );
    }

    [Fact]
    public void Match_RejectsMissingProvider()
    {
        Assert.False(
            new MatchMoviesQueryValidator().Validate(new MatchMoviesQuery(["a.mkv"], "")).IsValid
        );
    }

    [Theory]
    [InlineData("Шоу Трумана", 1998, true)]
    [InlineData("Шоу Трумана", null, true)] // год необязателен: в имени его часто нет
    [InlineData("", 1998, false)] // искать нечего
    [InlineData("Кино", 1800, false)] // раньше кинематографа
    [InlineData("Кино", 2300, false)]
    public void MatchOne_ChecksTitleAndYear(string title, int? year, bool valid)
    {
        var query = new MatchMovieQuery("file.mkv", title, year, "tmdb");

        Assert.Equal(valid, new MatchMovieQueryValidator().Validate(query).IsValid);
    }

    [Fact]
    public void Import_AcceptsBothSources()
    {
        var validator = new ImportMoviesCommandValidator();

        Assert.True(validator.Validate(new ImportMoviesCommand([FromManual()], "tmdb")).IsValid);
        Assert.True(validator.Validate(new ImportMoviesCommand([Uploaded()], "tmdb")).IsValid);
    }

    [Fact]
    public void Import_RejectsItemWithoutFile()
    {
        // Без файла шоу пустое — заводить его незачем.
        var item = new MovieImportItem(null, null, "Гладиатор", 2000, null);

        Assert.False(
            new ImportMoviesCommandValidator()
                .Validate(new ImportMoviesCommand([item], "tmdb"))
                .IsValid
        );
    }

    [Fact]
    public void Import_RejectsItemWithTwoSources()
    {
        // Путь в manual/ и уже загруженный ассет разом: неясно, какой файл брать.
        var item = new MovieImportItem("Gladiator.mkv", Guid.NewGuid(), "Гладиатор", 2000, null);

        Assert.False(
            new ImportMoviesCommandValidator()
                .Validate(new ImportMoviesCommand([item], "tmdb"))
                .IsValid
        );
    }

    [Fact]
    public void Import_RejectsEmptyTitle()
    {
        Assert.False(
            new ImportMoviesCommandValidator()
                .Validate(new ImportMoviesCommand([FromManual(title: " ")], "tmdb"))
                .IsValid
        );
    }

    [Fact]
    public void Import_RejectsEmptyBatch()
    {
        Assert.False(
            new ImportMoviesCommandValidator().Validate(new ImportMoviesCommand([], "tmdb")).IsValid
        );
    }
}
