using MediatR;
using Modules.Library.Application.Commands.CommonModels;
using Modules.Library.Application.Gateways;
using Modules.Library.Application.Services;
using Modules.Library.Domain.Entities.MediaContent.Items.Anime;

namespace Modules.Library.Application.Commands.Anime.Title;

public class CreateAnimeTitleCommand : IRequest<Guid>
{
    public IEnumerable<Name> Names { get; init; } = [];
    public MediaInfo? Preview {  get; set; }
    public IEnumerable<Description> Descriptions { get; init; } = [];
    public IEnumerable<Genre> Genres { get; init; } = [];
    public List<MediaInfo> RelatedContent { get; } = [];

    public DateTime? AnnouncementDate { get; init; }
    public DateTime? EstimatedReleaseDate { get; init; }
}

public class MediaInfo
{
    public MediaInfoType Type { get; init; }
    public string? ContentType { get; init; }
    public Stream? Data { get; init; }
    public string? Url { get; init; }
}

public class Name
{
    public Guid LanguageId { get; init; }
    public string Value { get; init; } = null!;
    public NameType NameType { get; init; }
}
public class Description
{
    public Guid LanguageId { get; init; }
    public string Value { get; init; } = null!;
    public bool IsOriginal { get; init; }
}
public class Genre
{
    public Guid GenreId { get; init; }
    public decimal? Proportion { get; init; }
}

public class CreateAnimeTitleCommandHandler(IAnimeTitleGateway titleGateway, ILanguageGateway languageGateway,
    IGenreGateway genreGateway, MediaInfoService mediaInfoService) : IRequestHandler<CreateAnimeTitleCommand, Guid>
{
    public async Task<Guid> Handle(CreateAnimeTitleCommand request, CancellationToken cancellationToken)
    {
        if (!request.Names.Any()) throw new Exception("No names");
        //var language = await languageGateway.GetLanguageById(request.NameLanguageId);
        var languages = (await languageGateway.GetLanguageByIds(request.Names.Select(q => q.LanguageId).Distinct())).ToArray();
        var genres = (await genreGateway.GetGenreByIds(request.Genres.Select(q => q.GenreId).Distinct())).ToArray();

        var animeTitle = new AnimeTitle(request.Names.Select(q =>
        new Domain.Entities.MediaContent.CommonProperties.NameItem((Domain.Entities.MediaContent.CommonProperties.NameType)q.NameType,
        languages.First(x => x.Id == q.LanguageId).Id, q.Value)));

        if (request.Descriptions.Any())
        {
            foreach (var description in request.Descriptions)
            {
                var languageId = languages.First(q => q.Id == description.LanguageId).Id;
                if (description.IsOriginal) animeTitle.CommonProperties.AddOriginalDescription(languageId, description.Value);
                else animeTitle.CommonProperties.AddNotOriginalDescription(languageId, description.Value);
            }
        }
        if (request.Genres.Any())
        {
            foreach (var genre in request.Genres)
            {
                var genreId = genres.First(q => q.Id == genre.GenreId).Id;
                animeTitle.CommonProperties.AddGenre(genreId, genre.Proportion);
            }
        }
        if (request.RelatedContent.Any())
        {
            foreach (var relatedContentItem in request.RelatedContent)
            {
                //add model
                var (objectId, contentType) = await mediaInfoService.Add(new MediaInfoService.CreateModel
                {
                    Data = relatedContentItem.Data,
                    Url = relatedContentItem.Url,
                    ContentType = relatedContentItem.ContentType,
                    Type = (Domain.Entities.MediaInfoType)relatedContentItem.Type,
                }, false, cancellationToken);
                
                //objectId
                animeTitle.CommonProperties.AddRelatedContent(objectId, (Domain.Entities.MediaInfoType)relatedContentItem.Type, contentType);
            }
        }

        animeTitle.CommonProperties.SetAnnouncementDate(request.AnnouncementDate);
        animeTitle.CommonProperties.SetEstimatedReleaseDate(request.EstimatedReleaseDate);
        //
        //animeTitle.CommonProperties.SetReleaseDate(request.ReleaseDate);
        var animeTitleId = await titleGateway.Create(animeTitle);
        if (request.Preview != null)
        {
            var title = await titleGateway.GetById(animeTitleId);
            var (objectId, contentType) = await mediaInfoService.Add(new MediaInfoService.CreateModel
            {
                Id = animeTitleId,
                Data = request.Preview.Data,
                Url = request.Preview.Url,
                ContentType = request.Preview.ContentType,
                Type = (Domain.Entities.MediaInfoType)request.Preview.Type,
            }, true, cancellationToken);
            title.CommonProperties.SetPreview(objectId, (Domain.Entities.MediaInfoType)request.Preview.Type, contentType);
            await titleGateway.Update(title);
        }
        //return await titleGateway.Create(animeTitle);
        return animeTitleId;
    }
}