using Hotline.Settings.TimeLimits;
using Hotline.Share.Dtos.Settings;
using XF.Domain.Dependency;

namespace Hotline.Settings.TimeLimitDomain.ExpireTimeSupplier;
public class WorkDaySupplier : IExpireTimeSupplier, IScopeDependency
{
    private readonly IDaySettingRepository _daySettingRepository;

    public WorkDaySupplier(IDaySettingRepository daySettingRepository)
    {
        _daySettingRepository = daySettingRepository;
    }

    public async Task<TimeResult> CalcEndTimeAsync(DateTime beginTime, TimeConfig timeConfig)
    {
        var startTime = beginTime;
        var startTimeOne = beginTime;
        if (timeConfig.WorkTime == null)
            return new TimeResult { EndTime = beginTime, RuleStr = timeConfig.Count + "个工作日", NearlyExpiredTime = beginTime, NearlyExpiredTimeOne = beginTime };

        //检查时间段内是否存在休息日或者工作日
        //查询统一部门工作时间
        //计算一天工作时间（分钟）
        DateTime WorkBeginTime = DateTime.Parse(beginTime.ToShortDateString() + " " + timeConfig.WorkTime[0] + ":00");
        DateTime WorkEndTime = DateTime.Parse(beginTime.ToShortDateString() + " " + timeConfig.WorkTime[1] + ":00");
        //计算一天多少个工作小时
        var duration = WorkEndTime - WorkBeginTime;
        double workMinutes = duration.TotalMinutes;
        double totalWorkMinutes = (workMinutes * timeConfig.Count) * (timeConfig.Percentage / 100.00);
        double totalWorkMinutesOne = (workMinutes * timeConfig.Count) * (timeConfig.PercentageOne / 100.00);

        //判断开始时间不在工时间段修正时间复位至当天或者第二天的开始时间（如果大于结束时间则复位至第二天的开始时间）
        if (beginTime < WorkBeginTime)
        {
            beginTime = WorkBeginTime;
        }
        else
        {
            if (beginTime > WorkEndTime)
            {
                beginTime = WorkBeginTime.AddDays(1);
            }
            if (await NotWorkDay(beginTime))
            {
                beginTime = WorkBeginTime.AddDays(1);
            }
        }

        while (true)
        {
            if (await IsWorkDay(beginTime))
            {
                break;
            }
            beginTime = beginTime.AddDays(1);
        }

        int day = 1;
        for (int i = 1;i < timeConfig.Count + 1;i++)
        {
            if (await IsWorkDay(beginTime.AddDays(day)))
            {
                beginTime = beginTime.AddDays(day);

                if (totalWorkMinutes >= workMinutes)
                {
                    startTime = startTime.AddDays(day);
                    totalWorkMinutes = totalWorkMinutes - workMinutes;
                }
                else if (totalWorkMinutes < workMinutes && totalWorkMinutes != 0)
                {
                    if (startTime.AddMinutes(totalWorkMinutes) > DateTime.Parse(startTime.ToShortDateString() + " " + timeConfig.WorkTime[1] + ":00"))
                    {
                        totalWorkMinutes = totalWorkMinutes - ((DateTime.Parse(startTime.ToShortDateString() + " " + timeConfig.WorkTime[1] + ":00") - startTime).TotalMinutes);
                        startTime = startTime.AddDays(day);
                        startTime = DateTime.Parse(startTime.ToShortDateString() + " " + timeConfig.WorkTime[0] + ":00").AddMinutes(totalWorkMinutes);
                        totalWorkMinutes = 0;
                    }
                    else
                    {
                        startTime = startTime.AddMinutes(totalWorkMinutes);
                    }
                }

                if (totalWorkMinutesOne >= workMinutes)
                {
                    startTimeOne = startTimeOne.AddDays(day);
                    totalWorkMinutesOne = totalWorkMinutesOne - workMinutes;
                }
                else if (totalWorkMinutesOne < workMinutes && totalWorkMinutesOne != 0)
                {
                    if (startTimeOne.AddMinutes(totalWorkMinutesOne) > DateTime.Parse(startTimeOne.ToShortDateString() + " " + timeConfig.WorkTime[1] + ":00"))
                    {
                        totalWorkMinutesOne = totalWorkMinutesOne - ((DateTime.Parse(startTimeOne.ToShortDateString() + " " + timeConfig.WorkTime[1] + ":00") - startTimeOne).TotalMinutes);
                        startTimeOne = startTimeOne.AddDays(day);
                        startTimeOne = DateTime.Parse(startTimeOne.ToShortDateString() + " " + timeConfig.WorkTime[0] + ":00").AddMinutes(totalWorkMinutesOne);
                        totalWorkMinutesOne = 0;
                    }
                    else
                    {
                        startTimeOne = startTimeOne.AddMinutes(totalWorkMinutesOne);
                    }
                }


                day = 1;
            }
            else
            {
                i--;
                day++;
            }
        }
        return new TimeResult { EndTime = beginTime, RuleStr = timeConfig.Count + "个工作日", NearlyExpiredTime = startTime, NearlyExpiredTimeOne = startTimeOne };
    }

    /// <summary>
    /// 是否是工作日
    /// 根据数据库的工作日和周末时间判断
    /// </summary>
    /// <param name="date"></param>
    /// <returns></returns>
    private async Task<bool> IsWorkDay(DateTime date)
    {
        return await _daySettingRepository.IsWorkDay(date);
    }

    private async Task<bool> NotWorkDay(DateTime date)
    {
        return !await IsWorkDay(date);
    }
}
