using AutoMapper;
using MediatR;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Mvc;
using Modules.Library.WebApi.Models.Anime;
using Modules.Library.WebApi.Models.Anime.CommonProperties;
using Modules.Library.WebApi.Models.Views.Anime;
using System.Net;

namespace Modules.Library.WebApi.Controllers;

[ApiController]
[ApiExplorerSettings(GroupName = "AnimeTitle1V1")]
[Route("MediaContent/Anime/Title1")]
//[Route("[controller]")]
[Authorize]
public class AnimeTitle1Controller : ControllerBase
{
    private readonly IMapper _mapper;
    private readonly IMediator _mediator;
    private readonly ILogger _logger;

    public AnimeTitle1Controller(IMapper mapper, IMediator mediator, ILogger<AnimeTitleController> logger)
    {
        _mapper = mapper;
        _mediator = mediator;
        _logger = logger;
    }

    [HttpGet]
    [AllowAnonymous]
    public async Task<Title> ById(Guid TitleId)
    {
        var title = await _mediator.Send(new Application.Queries.Anime.AnimeTitle.AnimeTitleQuery { Id = TitleId });
        var r = new Title
        {
            Id = title.Id,
            Deleted = title.Deleted,
            CommonProperties = GetCommonProperties(title.CommonProperties),
            ContainRates = title.Rate > 0,
            ContainViews = false,
            Items = title.Items.Select(GetAnimeItem),
            Completed = title.Completed,
            ExpirationTimeTicks = title.ExpirationTime.Ticks,
        };
        return new Title
        {
            Id = title.Id,
            Deleted = title.Deleted,
            CommonProperties = GetCommonProperties(title.CommonProperties),
            ContainRates = title.Rate > 0,
            ContainViews = false,
            Items = title.Items.Select(GetAnimeItem),
            Completed = title.Completed,
            ExpirationTimeTicks = title.ExpirationTime.Ticks,
        };
    }

    private static Models.Views.CommonProperties GetCommonProperties(Application.Models.CommonProperties commonProperties)
    {
        return new Models.Views.CommonProperties
        {
            Names = commonProperties.Names.Select(GetNameItem),
            Preview = commonProperties.Preview != null ? GetMediaInfo(commonProperties.Preview) : null,
            Descriptions = commonProperties.Descriptions.Select(q => new Models.Views.Description
            {
                Language = GetLanguage(q.Language),
                Value = q.Value,
                IsOriginal = q.IsOriginal,
            }),
            Genres = commonProperties.Genres.Select(GetGenreProportion),
            RelatedContent = commonProperties.RelatedContent.Select(GetMediaInfo),
            AnnouncementDate = commonProperties.AnnouncementDate,
            EstimatedReleaseDate = commonProperties.EstimatedReleaseDate,
            ReleaseDate = commonProperties.ReleaseDate,
        };
    }
    private static Models.Views.NameItem GetNameItem(Application.Models.NameItem nameItem)
    {
        return new Models.Views.NameItem
        {
            Type = (Models.NameType)nameItem.Type,
            Language = GetLanguage(nameItem.Language),
            Value = nameItem.Value,
        };
    }
    private static Models.Views.GenreProportion GetGenreProportion(Application.Models.GenreProportion genreProportion)
    {
        return new Models.Views.GenreProportion
        {
            Genre = new Models.Views.Dictionary.Genre
            {
                Id = genreProportion.Genre.Id,
                Name = genreProportion.Genre.Name,
                Deleted = genreProportion.Genre.Deleted,
            },
            Proportion = genreProportion.Proportion,
        };
    }
    private static Models.Views.Dictionary.Language GetLanguage(Application.Models.Language language)
    {
        return new Models.Views.Dictionary.Language
        {
            Id = language.Id,
            Name = language.Name,
            CodeIso3 = language.CodeIso3,
            Deleted = language.Deleted,
            IconId = language.IconId,
        };
    }
    private static Models.MediaInfo GetMediaInfo(Application.Models.MediaInfo mediaInfo)
    {
        return new Models.MediaInfo
        {
            Type = (Models.MediaInfoType)mediaInfo.Type,
            ContentType = mediaInfo.ContentType,
            ObjectId = mediaInfo.ObjectId,
        };
    }
    private static AnimeItem GetAnimeItem(Application.Models.Anime.AnimeItem item)
    {
        if (item is Application.Models.Anime.Season season)
        {
            return new Season
            {
                Id = season.Id,
                Deleted = season.Deleted,
                Completed = season.Completed,

                CommonProperties = GetCommonProperties(season.CommonProperties),
                Number = season.Number,
                Order = season.Order,
                ExpirationTimeTicks = season.ExpirationTime.Ticks,

                Director = season.Director,
                OriginCountry = season.OriginCountry,
                Episodes = season.Episodes.Select(GetAnimeItem).OfType<Episode>(),
            };
        }
        else if (item is Application.Models.Anime.Episode episode)
        {
            return new Episode
            {
                Id = episode.Id,
                Deleted = episode.Deleted,
                Completed = episode.Completed,

                CommonProperties = GetCommonProperties(episode.CommonProperties),
                Number = episode.Number,
                Order = episode.Order,
                ExpirationTimeTicks = episode.ExpirationTime.Ticks,

                Variant = episode.Variant,
                Type = (Models.AnimeEpisodeType)episode.Type,
                DurationTicks = episode.Duration?.Ticks,
            };
        }
        else throw new NotImplementedException();
    }
}