using ErsatzTV.Controllers.Api.Requests;
using ErsatzTV.Core.Domain;
using ErsatzTV.Infrastructure.Data;
using NUnit.Framework;
namespace ErsatzTV.Tests.Support;
///
/// One selection-type matrix, shared by every fixture that exercises a tagged-union selection
/// (rerun collections and playlist items). Both consumers of
/// MediaCollections.Mapper.ProjectMediaItemToViewModel are proved against the SAME data, so
/// widening the shared switch cannot be discharged for the second consumer by inspection alone —
/// which is the method that produced #671 in the first place.
///
internal static class SelectionSeedData
{
public const int SelectedId = 42;
///
/// Derived from production rather than hand-listed, so a newly-supported type joins the matrix
/// automatically and trips the default: arms below until someone teaches them about it.
/// Note this is the RERUN-COLLECTION predicate, used for playlist items as a deliberate
/// SUPERSET: ReplacePlaylistItemsHandler.CollectionTypeMustBeValid has no
/// RemoteStream case, so a RemoteStream playlist item cannot be created through the write
/// API today and the playlist fixture seeds that row directly. Covering it is forward-looking,
/// not a claim that the two sets are equivalent — split this if they ever legitimately diverge.
///
public static IEnumerable SupportedSelectionTypes =>
Enum.GetValues().Where(RerunCollectionRequestMapping.IsSupportedSelectionType);
///
/// The exact projected name per type. Pinning the whole string — rather than merely asserting
/// "not a placeholder" — is what makes a missing NESTED include leg visible: dropping
/// Episode → Season → Show still yields the placeholder-free "s??e04 - Selected episode", and
/// dropping MusicVideo → Artist still yields "Selected music video". Both would sail past a
/// looser assertion while having lost real data.
///
public static string ExpectedName(CollectionType collectionType) =>
collectionType switch
{
CollectionType.Collection => "Selected collection",
CollectionType.MultiCollection => "Selected multi collection",
CollectionType.SmartCollection => "Selected smart collection",
CollectionType.TelevisionShow => "Selected show (2020)",
CollectionType.TelevisionSeason => "Parent show (2020) - Season 3",
CollectionType.Artist => "Selected artist",
CollectionType.Movie => "Selected movie (2019)",
CollectionType.Episode => "Episode's show - s02e04 - Selected episode",
CollectionType.MusicVideo => "Video's artist - Selected music video",
CollectionType.OtherVideo => "Selected other video",
CollectionType.Song => "Song artist - Selected song",
CollectionType.Image => "Selected image",
CollectionType.RemoteStream => "Selected remote stream",
_ => throw new AssertionException($"No expected name pinned for {collectionType}")
};
public static async Task SeedSelection(TvContext context, CollectionType collectionType)
{
switch (collectionType)
{
case CollectionType.Collection:
context.Collections.Add(new Collection
{
Id = SelectedId,
Name = "Selected collection",
MediaItems = []
});
break;
case CollectionType.MultiCollection:
context.MultiCollections.Add(new MultiCollection
{
Id = SelectedId,
Name = "Selected multi collection"
});
break;
case CollectionType.SmartCollection:
context.SmartCollections.Add(new SmartCollection
{
Id = SelectedId,
Name = "Selected smart collection",
Query = "tag:family"
});
break;
case CollectionType.TelevisionShow:
context.Shows.Add(new Show
{
Id = SelectedId,
ShowMetadata = [new ShowMetadata { Title = "Selected show", Year = 2020 }]
});
break;
case CollectionType.TelevisionSeason:
context.Seasons.Add(new Season
{
Id = SelectedId,
SeasonNumber = 3,
Show = new Show
{
Id = 900,
ShowMetadata = [new ShowMetadata { Title = "Parent show", Year = 2020 }]
}
});
break;
case CollectionType.Artist:
context.Artists.Add(new Artist
{
Id = SelectedId,
ArtistMetadata = [new ArtistMetadata { Title = "Selected artist" }]
});
break;
case CollectionType.Movie:
context.Movies.Add(new Movie
{
Id = SelectedId,
MovieMetadata = [new MovieMetadata { Title = "Selected movie", Year = 2019 }]
});
break;
case CollectionType.Episode:
context.Episodes.Add(new Episode
{
Id = SelectedId,
EpisodeMetadata = [new EpisodeMetadata { Title = "Selected episode", EpisodeNumber = 4 }],
Season = new Season
{
Id = 901,
SeasonNumber = 2,
Show = new Show
{
Id = 902,
ShowMetadata = [new ShowMetadata { Title = "Episode's show", Year = 2018 }]
}
}
});
break;
case CollectionType.MusicVideo:
context.MusicVideos.Add(new MusicVideo
{
Id = SelectedId,
MusicVideoMetadata = [new MusicVideoMetadata { Title = "Selected music video" }],
Artist = new Artist
{
Id = 903,
ArtistMetadata = [new ArtistMetadata { Title = "Video's artist" }]
}
});
break;
case CollectionType.OtherVideo:
context.OtherVideos.Add(new OtherVideo
{
Id = SelectedId,
OtherVideoMetadata = [new OtherVideoMetadata { Title = "Selected other video" }]
});
break;
case CollectionType.Song:
context.Songs.Add(new Song
{
Id = SelectedId,
SongMetadata =
[new SongMetadata { Title = "Selected song", Artists = ["Song artist"] }]
});
break;
case CollectionType.Image:
context.Images.Add(new Image
{
Id = SelectedId,
ImageMetadata = [new ImageMetadata { Title = "Selected image" }]
});
break;
case CollectionType.RemoteStream:
context.RemoteStreams.Add(new RemoteStream
{
Id = SelectedId,
Url = "http://example.invalid/stream",
RemoteStreamMetadata = [new RemoteStreamMetadata { Title = "Selected remote stream" }]
});
break;
default:
throw new AssertionException(
$"{collectionType} is a supported selection type but this suite does not know how " +
"to seed it — teach SeedSelection about it rather than narrowing the matrix.");
}
await context.SaveChangesAsync();
}
///
/// Assigns the one foreign key the tagged union uses for this type. Shared so the rerun and
/// playlist fixtures cannot disagree about which slot a type occupies.
///
public static void ApplySelection(
CollectionType collectionType,
Action setCollectionId,
Action setMultiCollectionId,
Action setSmartCollectionId,
Action setMediaItemId)
{
switch (collectionType)
{
case CollectionType.Collection:
setCollectionId(SelectedId);
break;
case CollectionType.MultiCollection:
setMultiCollectionId(SelectedId);
break;
case CollectionType.SmartCollection:
setSmartCollectionId(SelectedId);
break;
default:
setMediaItemId(SelectedId);
break;
}
}
}