using System;
using System.Data.Entity;
using System.Linq;
using System.Threading.Tasks;
using EscapistasClub.Command.Interfaces;
using EscapistasClub.Core.Context;
using EscapistasClub.Core.Helpers;
using EscapistasClub.Core.Models;

namespace EscapistasClub.Command.Games.UpdateGame
{
    public class UpdateGameCommandHandler : IHandleCommand<UpdateGameCommand>
    {
        private readonly IApplicationDbContext _applicationDbContext;

        public UpdateGameCommandHandler(IApplicationDbContext applicationDbContext)
        {
            _applicationDbContext = applicationDbContext;
        }

        public async Task<CommandResult> Handle(UpdateGameCommand command)
        {
            var game = _applicationDbContext.Games.Find(command.Id);
            var place = _applicationDbContext.Places.Find(command.PlaceId);
            var gameTags = _applicationDbContext.TagGames.Where(tg => tg.GameId == command.Id);

            game.Name = command.Name;
            game.Status = command.Status;
            game.Place = place;
            game.Description = command.Description;
            game.Duration = command.Duration;
            game.GameType = command.GameType;
            game.MaxPlayers = command.MaxPlayers;
            game.MinPlayers = command.MinPlayers;
            game.PriceFrom = command.PriceFrom;
            game.PriceTo = command.PriceTo;
            game.Relevance = command.Relevance;
            game.Url = command.Url;
            game.YoutubeVideoUrl = command.YoutubeVideoUrl;


            var tagsToDelete = gameTags.Where(t => !command.Tags.Contains(t.Tag.Name)).ToList();

            foreach (var tagToDelete in tagsToDelete)
            {
                game.TagGames.Remove(tagToDelete);
            }

            var tagsToAdd = command.Tags.Where(t => gameTags.All(tg => !tg.Tag.Name.Equals(t, StringComparison.InvariantCultureIgnoreCase))).ToList();

            if (tagsToAdd.Any())
            {
                var tagSlugs = _applicationDbContext.Tags.Select(t => t.Slug).ToList();

                foreach (var tag in tagsToAdd)
                {
                    var newTag =
                        _applicationDbContext.Tags.FirstOrDefault(
                            t => t.Name.Equals(tag, StringComparison.InvariantCultureIgnoreCase));

                    if (newTag == null)
                    {
                        newTag = new Tag
                        {
                            Id = GuidHelper.NewGuid(),
                            Name = tag,
                            Slug = tag.GetSlug(tagSlugs)
                        };
                        _applicationDbContext.Tags.Add(newTag);
                    }

                    _applicationDbContext.TagGames.Add(new TagGame
                    {
                        GameId = game.Id,
                        TagId = newTag.Id
                    });
                }
            }


            await _applicationDbContext.SaveChangesAsync();

            return new CommandResult
            {
                EntityId = command.Id
            };
        }
    }
}