using System;
using System.Collections.Generic;
using System.Text;

namespace SessionCompanion.Services.Services
{
    using System.Linq;
    using System.Threading.Tasks;

    using AutoMapper;

    using Microsoft.EntityFrameworkCore;

    using SessionCompanion.Database.Repositories.Base;
    using SessionCompanion.Database.Tables;
    using SessionCompanion.Services.Base;
    using SessionCompanion.Services.Interfaces;
    using SessionCompanion.ViewModels.ApiResponses;
    using SessionCompanion.ViewModels.CharacterArmorViewModels;
    using SessionCompanion.Extensions.EitherType;
    using SessionCompanion.ViewModels.CharacterOtherEquipmentViewModels;

    public class CharacterArmorService : ServiceBase<CharacterArmorViewModel, CharacterArmor>, ICharacterArmorService
    {
        public CharacterArmorService(IMapper mapper, IRepository<CharacterArmor> repository) : base(mapper, repository)
        { }

        public async Task<Either<SuccessResponse, ErrorResponse>> ChangeCharacterArmor(int characterId, int newArmorId)
        {
            CharacterArmor armorInUse = new CharacterArmor();
            CharacterArmor armorToUse = new CharacterArmor();
            try
            {
                armorInUse = await Repository.Get(c => c.CharacterId.Equals(characterId))
                    .Include(a => a.Armor).Where(x => x.InUse == true).SingleAsync();
                armorToUse = await Repository.Get(c => c.ArmorId.Equals(newArmorId) && c.CharacterId.Equals(characterId)).SingleAsync();
            }
            catch (Exception e)
            {
                return new ErrorResponse() { StatusCode = 500, Message = e.Message };
            }

            if (armorToUse is null)
                return new ErrorResponse() { StatusCode = 204, Message = "No armor to change to" };

            if (armorInUse is null)
            {
                armorToUse.InUse = true;
                try
                {
                    await Repository.Update(armorToUse);
                    await Repository.Save();
                    return new SuccessResponse("Character armor updated") { SuccessCode = 200 };
                }
                catch (Exception e)
                {
                    return new ErrorResponse() { StatusCode = 500, Message = e.Message };
                }
            }

            armorInUse.InUse = false;
            armorToUse.InUse = true;
            try
            {
                await Repository.Update(armorInUse);
                await Repository.Update(armorToUse);
                await Repository.Save();
                return new SuccessResponse("Character armor updated") { SuccessCode = 204 };
            }
            catch (Exception e)
            {
                return new ErrorResponse() { StatusCode = 500, Message = e.Message };
            }
        }
        /// <summary>
        /// Metoda pobiera listę pancerzy konkretnej postaci
        /// </summary>
        /// <param name="characterId"> Id postaci </param>
        /// <returns> Lista pancerzy posiadanych przez postać </returns>
        public async Task<List<CharacterArmorViewModelDetails>> GetCharacterArmorsTaskList(int characterId)
        {
            var characterWeapons = await Repository.Get().Where(a => a.CharacterId.Equals(characterId)).Include(a => a.Armor).ToListAsync();

            var result = Mapper.Map<List<CharacterArmorViewModelDetails>>(characterWeapons);
            return result;
        }
    }
}