using AsbCloudApp.Data;
using AsbCloudApp.Services;
using AsbCloudDb.Model;
using Mapster;
using Microsoft.EntityFrameworkCore;
using System;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;

namespace AsbCloudInfrastructure.Repository
{
#nullable enable
    public class ScheduleRepository : CrudWellRelatedRepositoryBase<ScheduleDto, Schedule>, IScheduleRepository
    {
        private readonly IWellService wellService;

        public ScheduleRepository(IAsbCloudDbContext context, IWellService wellService)
            : base(context, dbSet => dbSet.Include(s => s.Driller))
        {
            this.wellService = wellService;
        }

        public async Task<DrillerDto?> GetOrDefaultDrillerAsync(int idWell, DateTime workTime, CancellationToken token)
        {
            var hoursOffset = wellService.GetTimezone(idWell).Hours;
            var date = workTime.ToUtcDateTimeOffset(hoursOffset);

            var entities = await GetQuery()
                .Where(s => s.IdWell == idWell
                    && s.DrillStart <= date
                    && s.DrillEnd >= date)
                .ToListAsync(token);

            if (!entities.Any())
                return null;

            var remoteDate = date.ToRemoteDateTime(hoursOffset);
            var time = new TimeOnly(remoteDate.Hour, remoteDate.Minute, remoteDate.Second);

            var entity = entities.FirstOrDefault(s =>
                s.ShiftStart > s.ShiftEnd ^
                (time >= s.ShiftStart && time < s.ShiftEnd)
            );

            return entity?.Driller.Adapt<DrillerDto>();
        }

        protected override Schedule Convert(ScheduleDto dto)
        {
            var hoursOffset = wellService.GetTimezone(dto.IdWell).Hours;
            var entity = base.Convert(dto);
            entity.DrillStart = dto.DrillStart.ToUtcDateTimeOffset(hoursOffset);
            entity.DrillEnd = dto.DrillEnd.ToUtcDateTimeOffset(hoursOffset);
            return entity;
        }

        protected override ScheduleDto Convert(Schedule entity)
        {
            var hoursOffset = wellService.GetTimezone(entity.IdWell).Hours;
            var dto = base.Convert(entity);
            dto.DrillStart = entity.DrillStart.ToRemoteDateTime(hoursOffset);
            dto.DrillEnd = entity.DrillEnd.ToRemoteDateTime(hoursOffset);
            return dto;
        }
    }
#nullable disable
}