using Brizco.Core.QuartzServices.Commands;
using Microsoft.Extensions.Logging;
using Quartz;

namespace Brizco.Core.QuartzServices.Handlers;

public class SetShiftPlanNotificationScheduleCommandHandler(IRepositoryWrapper repositoryWrapper,IScheduler scheduler,IMediator mediator,ILogger<SetShiftPlanNotificationScheduleCommand> logger) 
    : IRequestHandler<SetShiftPlanNotificationScheduleCommand,bool>
{
    public async Task<bool> Handle(SetShiftPlanNotificationScheduleCommand request, CancellationToken cancellationToken)
    {
        var shiftPlan = await repositoryWrapper.SetRepository<ShiftPlan>()
            .TableNoTracking
            .FirstOrDefaultAsync(sp => sp.Id == request.ShiftPlanId, cancellationToken);
        if (shiftPlan == null)
            throw new BaseApiException(ApiResultStatusCode.NotFound, "ShiftPlan not found in set schedule");

        var shift = await repositoryWrapper.SetRepository<Shift>()
            .TableNoTracking
            .FirstOrDefaultAsync(s => s.Id == shiftPlan.ShiftId, cancellationToken);

        if(shift == null)
            throw new BaseApiException(ApiResultStatusCode.NotFound, "Shift not found in set schedule");

        var shiftPlanUsers = await repositoryWrapper.SetRepository<ShiftPlanUser>()
            .TableNoTracking
            .Where(f => f.ShiftPlanId == request.ShiftPlanId)
            .ToListAsync(cancellationToken);

        foreach (var shiftPlanUser in shiftPlanUsers)
        {
            var completeShiftMessageForUser = $"شیفت‌های هفته بعد بسته شد، دیگه کار، کار، کار.";
            await mediator.Send(new CreateNotificationCommand(completeShiftMessageForUser, shiftPlanUser.UserId, shiftPlan.ComplexId), cancellationToken);
        }

        var shiftPlanStartAt = (new DateTime(shiftPlan.PlanFor.Year, shiftPlan.PlanFor.Month, shiftPlan.PlanFor.Day, shift.StartAt.Hours, shift.StartAt.Minutes, shift.StartAt.Seconds)).ToUniversalTime();
        var shiftPlanEndAt = (new DateTime(shiftPlan.PlanFor.Year, shiftPlan.PlanFor.Month, shiftPlan.PlanFor.Day, shift.EndAt.Hours, shift.EndAt.Minutes, shift.EndAt.Seconds)).ToUniversalTime();

        var currentDate = DateTime.UtcNow;

        var startTimeOffset = new DateTimeOffset(shiftPlanStartAt.Year, shiftPlanStartAt.Month, shiftPlanStartAt.Day, shiftPlanStartAt.Hour,
            shiftPlanStartAt.Minute, shiftPlanStartAt.Second, TimeSpan.Zero);
        var endTimeOffset = new DateTimeOffset(shiftPlanEndAt.Year, shiftPlanEndAt.Month, shiftPlanEndAt.Day, shiftPlanEndAt.Hour,
            shiftPlanEndAt.Minute, shiftPlanEndAt.Second, TimeSpan.Zero);



        IJobDetail beforeEndShift30Min = JobBuilder.Create<ShiftPlanNotificationScheduledJob>()
            .WithIdentity(ShiftPlanNotifyType.BeforeEndShift30Min.ToString(), shiftPlan.Id.ToString())
            .Build();
        ITrigger beforeEndShift30MinTrigger = TriggerBuilder.Create()
            .WithIdentity(StringExtensions.GetId(9), shift.ComplexId.ToString())
            .WithSimpleSchedule(x => x.WithRepeatCount(0))
            .StartAt(endTimeOffset.AddMinutes(-35))
            .Build();

        IJobDetail endOfShift = JobBuilder.Create<ShiftPlanNotificationScheduledJob>()
            .WithIdentity(ShiftPlanNotifyType.EndOfShift.ToString(), shiftPlan.Id.ToString())
            .Build();
        ITrigger endOfShiftTrigger = TriggerBuilder.Create()
            .WithIdentity(StringExtensions.GetId(9), shift.ComplexId.ToString())
            .WithSimpleSchedule(x => x.WithRepeatCount(0))
            .StartAt(endTimeOffset)
            .Build();


        IJobDetail afterStartShift2Hour = JobBuilder.Create<ShiftPlanNotificationScheduledJob>()
            .WithIdentity(ShiftPlanNotifyType.AfterStartShift2Hour.ToString(), shiftPlan.Id.ToString())
            .Build();
        ITrigger afterStartShift2HourTrigger = TriggerBuilder.Create()
            .WithIdentity(StringExtensions.GetId(9), shift.ComplexId.ToString())
            .WithSimpleSchedule(x => x.WithRepeatCount(0))
            .StartAt(startTimeOffset.AddHours(2))
            .Build();


        var seTimeOffsetA = await scheduler.ScheduleJob(beforeEndShift30Min, beforeEndShift30MinTrigger, cancellationToken);
        var seTimeOffsetB = await scheduler.ScheduleJob(endOfShift, endOfShiftTrigger, cancellationToken);
        var seTimeOffsetC = await scheduler.ScheduleJob(afterStartShift2Hour, afterStartShift2HourTrigger, cancellationToken);
        await scheduler.Start(cancellationToken);


        return true;
    }
}