using TeleWave.Application.Library.GetShow;
using TeleWave.Domain.Library;
using TeleWave.Domain.Media;
using TeleWave.Infrastructure.Persistence;
using Xunit;

namespace TeleWave.Integration.Tests;

/// <summary>
/// Карточка шоу против настоящей БД: запрос собирает серии, жанры и коллекции несколькими
/// проекциями, и часть из них EF может не суметь перевести — на InMemory такое не всплывает.
/// </summary>
[Collection("postgres")]
public sealed class GetShowIntegrationTests(PostgresFixture fixture)
{
    [SkippableFact]
    public async Task GetShow_ReturnsEpisodesGenresAndCollections()
    {
        Skip.IfNot(fixture.Available, "Docker недоступен");

        await using var seed = fixture.CreateContext();
        var showId = await SeedAsync(seed);

        await using var db = fixture.CreateContext();
        var result = await new GetShowQueryHandler(db).Handle(new GetShowQuery(showId), default);

        Assert.True(result.IsSuccess);
        Assert.Equal(2, result.Value.Episodes.Count);
        Assert.Equal(2, result.Value.Genres.Count);
        Assert.Single(result.Value.Collections);
        Assert.True(result.Value.Genres[0].IsPrimary);
        Assert.All(result.Value.Episodes, e => Assert.NotNull(e.AssetName));
    }

    [SkippableFact]
    public async Task GetShow_WithoutGenresAndCollections_Works()
    {
        Skip.IfNot(fixture.Available, "Docker недоступен");

        await using var seed = fixture.CreateContext();
        var show = Show.Create($"Голое шоу {Guid.NewGuid():N}"[..20], ShowKind.Series);
        seed.Shows.Add(show);
        await seed.SaveChangesAsync();

        await using var db = fixture.CreateContext();
        var result = await new GetShowQueryHandler(db).Handle(new GetShowQuery(show.Id), default);

        Assert.True(result.IsSuccess);
        Assert.Empty(result.Value.Episodes);
        Assert.Empty(result.Value.Genres);
        Assert.Empty(result.Value.Collections);
    }

    private static async Task<Guid> SeedAsync(AppDbContext db)
    {
        var tag = Guid.NewGuid().ToString("N")[..8];

        var action = Genre.Create($"Боевик {tag}", $"action-{tag}");
        var comedy = Genre.Create($"Комедия {tag}", $"comedy-{tag}");
        db.Genres.AddRange(action, comedy);

        var show = Show.Create($"Шоу {tag}", ShowKind.Series);
        for (var i = 0; i < 2; i++)
        {
            var asset = MediaAsset.Register($"{tag}-s01e0{i}.mkv", ".mkv", MediaSource.Upload);
            db.MediaAssets.Add(asset);
            show.AddEpisode(asset.Id);
        }
        show.SetGenres([action.Id, comedy.Id], action.Id);
        db.Shows.Add(show);
        await db.SaveChangesAsync();

        var collection = Collection.Create($"Франшиза {tag}");
        collection.AddShow(show.Id);
        db.Collections.Add(collection);
        await db.SaveChangesAsync();

        return show.Id;
    }
}
