using Hotline.Caching.Interfaces;
using Hotline.Settings.TimeLimits;
using Hotline.Share.Dtos.Settings;
using System.ComponentModel.DataAnnotations;
using XF.Domain.Dependency;

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

    public WorkDaySupplier(IDaySettingCacheManager daySettingCacheManager)
    {
        _daySettingCacheManager = daySettingCacheManager;
    }

    //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="beginTime"></param>
    /// <param name="timeConfig"></param>
    /// <returns></returns>
    public async Task<TimeResult> CalcEndTimeNewAsync(DateTime beginTime,DateTime startTime,TimeConfig timeConfig)
    {
        //------------------------------New
        var isWorkSend = await IsWorkDay(beginTime);

        var startTimeOne = startTime;//即将超期时间50%；

        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");

        if (timeConfig.EndType == null)
        {
            timeConfig.EndType = 1;
        }
        //获取期满时间收尾方式
        var endType = timeConfig.EndType;

        switch (endType)
        {
            case 0:
                if (!isWorkSend)
                {
                    beginTime = WorkBeginTime;
                }
                int q = timeConfig.Count;
                while (true && q != 0)
                {
                    if (await IsWorkDay(beginTime))
                    {
                        beginTime = beginTime.AddDays(1);
                        q--;
                    }
                    else
                    {
                        beginTime = beginTime.AddDays(1);
                    }
                }
                beginTime = beginTime.AddSeconds(-1);
                while (true)
                {
                    if (await IsWorkDay(beginTime))
                    {
                        break;
                    }
                    else
                    {
                        beginTime = beginTime.AddDays(1);
                    }
                }
                var sconds = (beginTime - startTime).TotalSeconds * (timeConfig.Percentage / 100.00);
                startTime = startTime.AddSeconds(sconds);
                var scondsOne = (beginTime - startTimeOne).TotalSeconds * (timeConfig.PercentageOne / 100.00);
                startTimeOne = startTimeOne.AddSeconds(scondsOne);
                break;
            case 1:

                //计算一天多少个工作小时
                var durationType1 = WorkEndTime - WorkBeginTime;
                double workMinutesType1 = durationType1.TotalMinutes;
                

                #region 计算期满时间
                if (!isWorkSend)
                {
                    beginTime = WorkBeginTime;
                    startTime = WorkBeginTime;
                    startTimeOne = WorkBeginTime;
                }
                while (true)
                {

                    if (!await IsWorkDay(beginTime))
                        beginTime = beginTime.AddDays(1);
                    else
                        break;
                }
                int w = timeConfig.Count;
                int days = 1;
                while (true && w != 0)
                {
                    if (await IsWorkDay(beginTime.AddDays(days)))
                    {
                        beginTime = beginTime.AddDays(days);
                        w--;
                        days = 1;
                    }
                    else
                    {
                        //beginTime = beginTime.AddDays(1);
                        days++;
                    }
                }
                beginTime = beginTime.AddSeconds(-1);
                while (true)
                {
                    if (await IsWorkDay(beginTime))
                    {
                        if (beginTime < DateTime.Parse(beginTime.ToShortDateString() + " " + timeConfig.WorkTime[0] + ":00"))
                        {
                            beginTime = DateTime.Parse(beginTime.AddDays(-1).ToShortDateString() + " " + timeConfig.WorkTime[1] + ":00");
                        }
                        else
                        {
                            break;
                        }
                    }
                    else if (!await IsWorkDay(beginTime))
                    {
                        beginTime = DateTime.Parse(beginTime.AddDays(-1).ToShortDateString() + " " + timeConfig.WorkTime[1] + ":00");
                    }
                    //else
                    //{
                    //    beginTime = beginTime.AddDays(1);
                    //}
                }
                #endregion

                var dayIndex = 1;
                var configCount = 1;
                while(true)
                {
                    if (startTime.AddDays(dayIndex).Date!= beginTime.Date)
                    {
                        if (await IsWorkDay(startTime.AddDays(dayIndex)))
                        {

                            configCount++;
                        }
                        dayIndex++;
                    }
                    else
                    {
                        break;
                    }
                }

                double totalWorkMinutesType1 = (workMinutesType1 * configCount) * (timeConfig.Percentage / 100.00);
                double totalWorkMinutesOneType1 = (workMinutesType1 * configCount) * (timeConfig.PercentageOne / 100.00);



                //计算即将超期时间
                while (true)
                {
                    if (!await IsWorkDay(startTime))
                        startTime = startTime.AddDays(1);
                    else
                        break;
                }

                days = 1;
                while (true && totalWorkMinutesType1 != 0)
                {
                    if (await IsWorkDay(startTime.AddDays(days)))
                    {
                        if (totalWorkMinutesType1 > workMinutesType1)
                        {
                            startTime = startTime.AddDays(days);
                            totalWorkMinutesType1 = totalWorkMinutesType1 - workMinutesType1;
                            days = 1;
                        }
                        else
                        {
                            if (startTime.AddMinutes(totalWorkMinutesType1) > DateTime.Parse(startTime.ToShortDateString() + " " + timeConfig.WorkTime[1] + ":00"))
                            {
                                totalWorkMinutesType1 = totalWorkMinutesType1 - ((DateTime.Parse(startTime.ToShortDateString() + " " + timeConfig.WorkTime[1] + ":00") - startTime).TotalMinutes);
                                startTime = startTime.AddDays(days);
                                startTime = DateTime.Parse(startTime.ToShortDateString() + " " + timeConfig.WorkTime[0] + ":00").AddMinutes(totalWorkMinutesType1);
                                totalWorkMinutesType1 = 0;
                                days = 1;
                            }
                            else
                            {
                                startTime = startTime.AddMinutes(totalWorkMinutesType1);
                                totalWorkMinutesType1 = 0;
                                days = 1;
                            }
                        }
                    }
                    else
                    {
                        days++;
                    }
                }

                //计算50%即将超期时间
                while (true)
                {
                    if (!await IsWorkDay(startTimeOne))
                        startTimeOne = startTimeOne.AddDays(1);
                    else
                        break;
                }

                days = 1;
                while (true && totalWorkMinutesOneType1 != 0)
                {
                    if (await IsWorkDay(startTimeOne.AddDays(days)))
                    {
                        if (totalWorkMinutesOneType1 > workMinutesType1)
                        {
                            startTimeOne = startTimeOne.AddDays(days);
                            totalWorkMinutesOneType1 = totalWorkMinutesOneType1 - workMinutesType1;
                            days = 1;
                        }
                        else if (totalWorkMinutesOneType1 <= workMinutesType1)
                        {
                            if (startTimeOne.AddMinutes(totalWorkMinutesOneType1) > DateTime.Parse(startTimeOne.ToShortDateString() + " " + timeConfig.WorkTime[1] + ":00"))
                            {
                                totalWorkMinutesOneType1 = totalWorkMinutesOneType1 - ((DateTime.Parse(startTimeOne.ToShortDateString() + " " + timeConfig.WorkTime[1] + ":00") - startTimeOne).TotalMinutes);
                                startTimeOne = startTimeOne.AddDays(days);
                                startTimeOne = DateTime.Parse(startTimeOne.ToShortDateString() + " " + timeConfig.WorkTime[0] + ":00").AddMinutes(totalWorkMinutesOneType1);
                                totalWorkMinutesOneType1 = 0;
                                days = 1;
                            }
                            else
                            {
                                startTimeOne = startTimeOne.AddMinutes(totalWorkMinutesOneType1);
                                totalWorkMinutesOneType1 = 0;
                                days = 1;
                            }
                        }
                    }
                    else
                    {
                        days++;
                    }
                }
                break;
            case 2:
                //期满时间注释延用老时间
                //startTime = beginTime;
                //startTimeOne = beginTime;
                //计算一天多少个工作小时
                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++;
                    }
                }
                break;
            case 3:

                break;
            default:
                break;
        }
        
        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 _daySettingCacheManager.IsWorkDay(date);
    }

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