using Coravel.Invocable;
using Coravel.Mailer.Mail.Interfaces;
using EnotaryoPH.Data;
using EnotaryoPH.Web.Common.Jobs.Models;
using EnotaryoPH.Web.Common.Models;
using EnotaryoPH.Web.Mailables;

namespace EnotaryoPH.Web.Common.Jobs
{
    public class OneTimePasswordInvocable : IInvocable, IInvocableWithPayload<OTPEmailModel>
    {
        private readonly IMailer _mailer;
        private readonly NotaryoDBContext _notaryoDBContext;
        private readonly Settings _settings;
        private readonly IPasswordService _passwordService;
        private readonly IEventService _eventService;

        public OneTimePasswordInvocable(IMailer mailer, NotaryoDBContext notaryoDBContext, Settings settings, IPasswordService passwordService, IEventService eventService)
        {
            _mailer = mailer;
            _notaryoDBContext = notaryoDBContext;
            _settings = settings;
            _passwordService = passwordService;
            _eventService = eventService;
        }

        public OTPEmailModel Payload { get; set; }

        public async Task Invoke()
        {
            var schedule = _notaryoDBContext.LawyerVideoConferenceSchedules
                .AsNoTracking()
                .Include(sched => sched.Transaction)
                .ThenInclude(transaction => transaction.TransactionDocument)
                .Include(sched => sched.Transaction)
                .ThenInclude(transaction => transaction.Lawyer)
                .ThenInclude(lawyer => lawyer.User)
                .Include(sched => sched.LawyerVideoConferenceParticipants)
                .ThenInclude(participant => participant.Participant)
                .FirstOrDefault(sched => sched.Transaction.Transaction_UID == Payload.Transaction_UID);

            if (schedule == null)
            {
                return;
            }

            var participantDic = schedule.LawyerVideoConferenceParticipants.ToDictionary(p => p.LawyerVideoConferenceParticipant_UID.GetValueOrDefault(), p => p);
            foreach (var otp in Payload.ParticipantOTP)
            {
                if (!participantDic.ContainsKey(otp.Key))
                {
                    continue;
                }
                var participant = participantDic[otp.Key];

                var emailViewModel = new OneTimePasswordViewModel
                {
                    DocumentType = schedule.Transaction.TransactionDocument.DocumentType,
                    Email = participant.Participant.Email,
                    OTP = otp.Value,
                    ParticipantName = participant.Participant.Fullname,
                    LawyerName = schedule.Transaction.Lawyer.User.Fullname,
                    MeetingRoomURL = $"{_settings.BaseUrl}/Participant/VideoCall/Room/{schedule.Transaction.Transaction_UID}",
                };
                await _mailer.SendAsync(new OneTimePasswordMailable(emailViewModel));
                await _eventService.LogAsync(NotaryoEvent.OTPSent, Payload.Transaction_UID, new
                {
                    emailViewModel.Email,
                    emailViewModel.ParticipantName,
                    emailViewModel.MeetingRoomURL
                });
            }
        }
    }
}