using BukiVedi.Shared.Entities;
using BukiVedi.Shared.Models;
using BukiVedi.Shared.Services;
using BukiVedi.Shared.Services.Mappers;

namespace BukiVedi.Shared.Apps
{
    public class AuthorHandler
        : IAuthorHandler
    {
        private readonly ILibrary _library;
        public AuthorHandler(ILibrary library)
        {
            if (library == null) throw new ArgumentNullException(nameof(library));
            _library = library;
        }

        public async Task AddToFavorite(string id, OperationContext context)
        {
            if (await Tables.FavoriteAuthors.Exists(Filters.FavoriteAuthors.Exact(id, context.OperationInitiator.Id)) == false)
            {
                await Tables.FavoriteAuthors.Write(new FavoriteAuthor { AuthorId = id, UserId = context.OperationInitiator.Id });
            }
        }

        public async Task<IEnumerable<AuthorInfo>> GetAllAuthors(OperationContext context) =>
            (await Tables.Authors.GetAll()).Select(a => new AuthorInfo { Id = a.Id, Name = a.Name })?.ToArray()!;

        public async Task<IEnumerable<AuthorInfo>> GetFavoriteAuthors(OperationContext context)
        {
            var authorIds = (await Tables.FavoriteAuthors.Get(Filters.FavoriteAuthors.ByUser(context.OperationInitiator.Id)))?.Select(f => f.AuthorId)?.ToHashSet()!;
            if (authorIds != null && authorIds.Any())
            {
                var authors = (await Tables.Authors.Get(Filters.Authors.ByIds(authorIds)))?.Select(a => new AuthorInfo { Id = a.Id, Name = a.Name })?.ToArray()!;
                return authors;
            }
            return Enumerable.Empty<AuthorInfo>();
        }

        public async Task RemoveFromFavorite(string id, OperationContext context)
        {
            var records = (await Tables.FavoriteAuthors.Get(Filters.FavoriteAuthors.Exact(id, context.OperationInitiator.Id)))?.ToHashSet()!;
            if (records != null && records.Count > 0)
            {
                foreach (var record in records)
                {
                    await Tables.FavoriteAuthors.TryRemoveById(record.Id);
                }
            }
        }

        public async Task<IEnumerable<BookInfo>> SearchByAuthor(string id, OperationContext context)
        {
            var books = (await _library.SearchBooksByAuthor(id))?.ToArray()!;
            if (books != null && books.Any())
            {
                return await BookEntityMapper.Map(books, context);
            }
            return Enumerable.Empty<BookInfo>();
        }
    }
}
