using AutoMapper;
using UserManagement.Common.UnitOfWork;
using UserManagement.Data;
using UserManagement.Data.Dto;
using UserManagement.Domain;
using UserManagement.Helper;
using UserManagement.MediatR.CommandAndQuery;
using UserManagement.Repository;
using MediatR;
using Microsoft.EntityFrameworkCore;
using System.Threading;
using System.Threading.Tasks;

namespace UserManagement.MediatR.Handlers
{
    public class UpdateReminderCommandHandler
      : IRequestHandler<UpdateReminderCommand, ServiceResponse<ReminderDto>>
    {

        private readonly IReminderRepository _reminderRepository;
        private readonly IReminderUserRepository _reminderUserRepository;
        private readonly IDailyReminderRepository _dailyReminderRepository;
        private readonly IQuarterlyReminderRepository _quarterlyReminderRepository;
        private readonly IHalfYearlyReminderRepository _halfYearlyReminderRepository;
        private readonly IMapper _mapper;
        private readonly IUnitOfWork<UserContext> _uow;

        public UpdateReminderCommandHandler(IReminderRepository reminderRepository,
            IReminderUserRepository reminderUserRepository,
            IDailyReminderRepository dailyReminderRepository,
            IQuarterlyReminderRepository quarterlyReminderRepository,
            IHalfYearlyReminderRepository halfYearlyReminderRepository,
            IMapper mapper,
            IUnitOfWork<UserContext> uow)
        {
            _reminderRepository = reminderRepository;
            _reminderUserRepository = reminderUserRepository;
            _dailyReminderRepository = dailyReminderRepository;
            _quarterlyReminderRepository = quarterlyReminderRepository;
            _halfYearlyReminderRepository = halfYearlyReminderRepository;
            _mapper = mapper;
            _uow = uow;
        }

        public async Task<ServiceResponse<ReminderDto>> Handle(UpdateReminderCommand request, CancellationToken cancellationToken)
        {
            var entity = await _reminderRepository
                .AllIncluding(c => c.DailyReminders, cs => cs.QuarterlyReminders, h => h.HalfYearlyReminders, u => u.ReminderUsers).FirstOrDefaultAsync(c => c.Id == request.Id);
            if (entity == null)
            {
                return ServiceResponse<ReminderDto>.Return404();
            }

            if (!request.IsRepeated)
            {
                request.Frequency = Frequency.OneTime;
            }

            _reminderUserRepository.RemoveRange(entity.ReminderUsers);
            _dailyReminderRepository.RemoveRange(entity.DailyReminders);
            _quarterlyReminderRepository.RemoveRange(entity.QuarterlyReminders);
            _halfYearlyReminderRepository.RemoveRange(entity.HalfYearlyReminders);

            if (!request.Frequency.HasValue)
            {
                request.Frequency = Frequency.OneTime;
            }

            var reminder = _mapper.Map(request, entity);
            if (!request.IsRepeated)
            {
                reminder.Frequency = null;
                reminder.DayOfWeek = null;
            }
            _reminderRepository.Update(reminder);

            if (await _uow.SaveAsync() <= -1)
            {
                return ServiceResponse<ReminderDto>.Return500();
            }

            return ServiceResponse<ReminderDto>.ReturnResultWith201(_mapper.Map<ReminderDto>(reminder));
        }
    }
}
