using Modules.Library.Domain.Entities;
using Modules.Library.Domain.Entities.Genre;
using Modules.Library.Domain.Entities.Language;
using Modules.Library.Domain.Entities.MediaContent.CommonProperties;

namespace Modules.Library.Domain.EntityBuilders;

public class CommonPropertiesBuilder : ValueObjectBuilder<CommonProperties>
{
    private static readonly Func<CommonProperties> CreateInstanceFunc = CreateInstanceFunction();
    private static readonly Action<CommonPropertiesBuilder, CommonProperties> SetInstanceFieldsAction = SetInstanceFieldsAction<CommonPropertiesBuilder>();

    private readonly List<NameItem> _names = [];
    private MediaInfo? _preview = null;
    private readonly List<Description> _descriptions = [];
    private readonly List<GenreProportion> _genres = [];
    private readonly List<MediaInfo> _relatedContent = [];
    private DateTimeOffset? _announcementDate = null;
    private DateTimeOffset? _estimatedReleaseDate = null;
    private DateTimeOffset? _releaseDate = null;

    public CommonPropertiesBuilder AddName(Guid languageId, NameType type, string value)
    {
        _names.Add(new NameItem(languageId, type, value));
        return this;
    }

    public CommonPropertiesBuilder SetPreview(string url, MediaInfoType type, string contentType)
    {
        _preview = new MediaInfo(url, type, contentType);
        return this;
    }

    public CommonPropertiesBuilder AddDescription(Guid languageId, bool isOriginal, string value)
    {
        _descriptions.Add(new Description(languageId, isOriginal, value));
        return this;
    }

    public CommonPropertiesBuilder AddGenreProportion(Genre genre, decimal? proportion)
    {
        _genres.Add(new GenreProportion(genre.Id, proportion));
        return this;
    }

    public CommonPropertiesBuilder AddRelatedContent(string url, MediaInfoType type, string contentType)
    {
        _relatedContent.Add(new MediaInfo(url, type, contentType));
        return this;
    }

    public CommonPropertiesBuilder SetAnouncementDate(DateTimeOffset? value)
    {
        _announcementDate = value;
        return this;
    }

    public CommonPropertiesBuilder SetEstimatedReleaseDate(DateTimeOffset? value)
    {
        _estimatedReleaseDate = value;
        return this;
    }

    public CommonPropertiesBuilder SetReleaseDate(DateTimeOffset? value)
    {
        _releaseDate = value;
        return this;
    }

    internal static CommonPropertiesBuilder FromCommonProperties(CommonProperties item)
    {
        var builder = new CommonPropertiesBuilder();

        foreach (var name in item.Names) { builder.AddName(name.LanguageId, name.Type, name.Value); }

        if (item.Preview != null) builder
                .SetPreview(item.Preview.ObjectId, item.Preview.Type, item.Preview.ContentType);

        foreach (var description in item.Descriptions) { builder.AddDescription(description.LanguageId, description.IsOriginal, description.Value); }
        //foreach (var genreProportion in item.Genres) { builder.AddGenreProportion(genreProportion.GenreId, genreProportion.Proportion); }
        foreach (var repatedContent in item.RelatedContent) { builder.AddRelatedContent(repatedContent.ObjectId, repatedContent.Type, repatedContent.ContentType); }

        builder.SetAnouncementDate(item.AnnouncementDate);
        builder.SetEstimatedReleaseDate(item.EstimatedReleaseDate);
        builder.SetReleaseDate(item.ReleaseDate);

        return builder;
    }

    public override CommonProperties Build() => throw new NotImplementedException();

    internal CommonProperties BuildObject()
    {
        var result = CreateInstanceFunc();
        SetInstanceFieldsAction(this, result);
        return result;
    }
}