using APT.BaseData.Domain.ApiModel.Platform;
using APT.BaseData.Domain.Entities.FM;
using APT.BaseData.Domain.Enums;
using APT.Infrastructure.Core;
using APT.Utility;
using Microsoft.AspNetCore.Mvc;
using System;
using System.Collections.Generic;
using System.Linq;

namespace APT.FM.WebApi.Controllers.Api.FM
{
    /// <summary>
    /// 排班跑批
    /// </summary>
    [Route("api/FM/Shift")]
    public class ShiftRunningController : AuthorizeApiController<T_FM_BASE_CONFIG>
    {
        /// <summary>
        /// 排班跑批接口
        /// </summary>
        /// <param name="entity"></param>
        /// <returns></returns>
        [HttpPost, Route("Running")]
        public JsonActionResult<bool> Running([FromBody] KeywordFilter filter)
        {
            return SafeExecute<bool>(() =>
            {
                var baseConfig = this.GetEntityByRedis<T_FM_BASE_CONFIG>(filter.GetOrgId().ToString(), filter.GetOrgId());
                if (baseConfig == null)
                    this.ThrowError("010002");
                var perDay = baseConfig.CALENDAR_DAYS;
                var perEndDay = DateTime.Now.AddDays(perDay).Date;
                //获取日历配置表
                var configData = this.GetEntities<T_FM_DEPARTMENT_CALENDAR_CONFIG>(d => d.ENABLE_STATUS == Convert.ToInt32(FMEnableStatusEnum.启用)
                && d.ORG_ID == filter.OrgId && d.CURR_TIME < perEndDay && d.END_TIME >= DateTime.Now
                && d.Nav_DepartmentCalendarConfigDetail.Any()
                && d.Nav_DepartmentCalendarConfigTeam.Any(), filter,
                "Nav_Calendar.Nav_Holiday.Nav_HolidayDetails",
                "Nav_DepartmentCalendarConfigDetail", "Nav_DepartmentCalendarConfigTeam").ToList();
                var classIds = configData.SelectMany(i => i.Nav_DepartmentCalendarConfigDetail).Select(i => i.CLASS_ID).ToArray();
                var teamIds = configData.SelectMany(i => i.Nav_DepartmentCalendarConfigTeam).Select(i => i.TEAM_ID).ToArray();
                var allClass = this.GetEntities<T_FM_CLASS>(i => classIds.Contains(i.ID), filter);
                var allTeamPersons = this.GetEntities<T_FM_TEAM_PERSON>(i => teamIds.Contains(i.TEAM_ID), filter);
                List<T_FM_DEPARTMENT_SCHEDULING> shiftList = new List<T_FM_DEPARTMENT_SCHEDULING>();//排版表
                List<T_FM_DEPARTMENT_SCHEDULING_DETAIL> shiftDetailList = new List<T_FM_DEPARTMENT_SCHEDULING_DETAIL>();//排版明细表
                var nodelModels = new List<ControlNodelModel>();//所有生产单元
                var baseFilter = new BaseFilter(filter.OrgId);
                baseFilter.Order = DbOrder.ASC;
                baseFilter.Level = -1;
                baseFilter.IsParentData = false;
                baseFilter.SelectField = new string[] { "ID" };
                var workShops = this.GetEntities<T_FM_DEPARTMENT>(x => x.DEPARTMENT_TYPE == (int)FMDepartmentType.车间, baseFilter);
                string[] Day = new string[] { "星期日", "星期一", "星期二", "星期三", "星期四", "星期五", "星期六" };
                foreach (var nodelModel in workShops)
                {
                    var shopCalenDarConfgs = configData.Where(i => i.DEPARTMENT_ID == nodelModel.ID).ToList();
                    foreach (var sh in shopCalenDarConfgs)
                    {
                        //通过第一个班组判断顺序
                        var orderTeam = sh.Nav_DepartmentCalendarConfigTeam.OrderBy(i => i.NUM).ToList();
                        var groupOrderTeam = orderTeam.GroupBy(i => i.NUM).ToList();
                        var orderClass = sh.Nav_DepartmentCalendarConfigDetail.OrderBy(i => i.NUM).ToList();
                        var fristTeam = orderTeam.FirstOrDefault();
                        var fristClass = orderClass.FirstOrDefault();
                        //排序排班的最后几条记录
                        BasePageFilter pageFilter = new BasePageFilter(1, sh.CYCLE);
                        pageFilter.OrgId = filter.OrgId;
                        pageFilter.Order = DbOrder.DESC;
                        pageFilter.Sort = "DATE_TIME";
                        var shiftData = this.GetOrderPageEntities<T_FM_DEPARTMENT_SCHEDULING>(s => s.DEPARTMENT_CALENDAR_CONFIG_ID == sh.ID
                        && s.DATE_TIME < sh.CURR_TIME && s.TEAM_ID == fristTeam.ID, pageFilter);
                        var dayIndex = 0;
                        var classIndex = 0;
                        Guid lastClassId = fristClass.ID;
                        if (shiftData != null && shiftData.Data.Any())
                        {
                            var pageData = shiftData.Data.ToList();
                            for (var index = 0; index < shiftData.Data.Count(); index++)
                            {
                                if (index == 0)
                                {
                                    lastClassId = pageData[index].CLASS_ID;
                                    var nowClass = sh.Nav_DepartmentCalendarConfigDetail.FirstOrDefault(i => i.CLASS_ID == lastClassId);
                                    classIndex = sh.Nav_DepartmentCalendarConfigDetail.Count(i => i.NUM < nowClass.NUM);
                                    dayIndex++;
                                }
                                else
                                {
                                    if (lastClassId == pageData[index].CLASS_ID)
                                    {
                                        dayIndex++;
                                        continue;
                                    }
                                    else
                                    {
                                        break;
                                    }
                                }
                            }
                        }

                        var totalCurrentIndex = classIndex * sh.CYCLE + dayIndex;//总的顺序
                        var totalIndex = sh.Nav_DepartmentCalendarConfigTeam.Count * sh.CYCLE;
                        for (var starTime = sh.CURR_TIME; starTime <= perEndDay; starTime = starTime.AddDays(1))
                        {

                            bool isWork = true;
                            var holidayWeeks = sh.Nav_Calendar.Nav_Holiday;
                            string week = Day[Convert.ToInt32(starTime.DayOfWeek.ToString("d"))].ToString();
                            switch (week)
                            {
                                case "星期一":
                                    isWork = holidayWeeks.MON;
                                    break;
                                case "星期二":
                                    isWork = holidayWeeks.TUES;
                                    break;
                                case "星期三":
                                    isWork = holidayWeeks.WED;
                                    break;
                                case "星期四":
                                    isWork = holidayWeeks.THUR;
                                    break;
                                case "星期五":
                                    isWork = holidayWeeks.FRI;
                                    break;
                                case "星期六":
                                    isWork = holidayWeeks.SAT;
                                    break;
                                case "星期日":
                                    isWork = holidayWeeks.SUN;
                                    break;
                                default:
                                    break;
                            }
                            var holidayDetails = sh.Nav_Calendar.Nav_Holiday.Nav_HolidayDetails;//假期详情
                            foreach (var holidayDetail in holidayDetails)
                            {
                                if (holidayDetail.START_TIME.Date <= starTime.Date && holidayDetail.END_TIME.Date >= starTime.Date && !holidayDetail.WORK)//休息日
                                    isWork = false;
                            }
                            if (isWork)
                            {
                                //一个循环结束
                                if (totalCurrentIndex == totalIndex)
                                {
                                    totalCurrentIndex = 0;
                                    classIndex = 0;
                                    dayIndex = 0;
                                }
                                //一个周期换班次
                                if (dayIndex == sh.CYCLE)
                                {
                                    classIndex++;
                                    dayIndex = 0;
                                }
                                for (var t = 0; t < groupOrderTeam.Count; t++)
                                {

                                    var teamClasIndex = (classIndex + t) % groupOrderTeam.Count;
                                    foreach (var team in groupOrderTeam[t])
                                    {
                                        T_FM_DEPARTMENT_SCHEDULING shift = new T_FM_DEPARTMENT_SCHEDULING
                                        {
                                            ID = Guid.NewGuid(),
                                            ORG_ID = filter.OrgId,
                                            DEPARTMENT_ID = (Guid)sh.DEPARTMENT_ID,
                                            DEPARTMENT_CALENDAR_CONFIG_ID = sh.ID,
                                            DATE_TIME = starTime,
                                            CLASS_ID = orderClass[teamClasIndex].CLASS_ID,
                                            TEAM_ID = team.TEAM_ID,
                                            ENABLE_STATUS = Convert.ToInt32(FMEnableStatusEnum.启用)
                                        };
                                        shiftList.Add(shift);

                                        var theClass = allClass.FirstOrDefault(i => i.ID == shift.CLASS_ID);
                                        if (theClass != null)
                                        {
                                            var teamPersons = allTeamPersons.Where(i => i.TEAM_ID == shift.TEAM_ID).ToList();
                                            foreach (var teamPerson in teamPersons)
                                            {
                                                var schDetail = new T_FM_DEPARTMENT_SCHEDULING_DETAIL
                                                {
                                                    ID = Guid.NewGuid(),
                                                    DEPARTMENT_SCHEDULING_ID = shift.ID,
                                                    PERSON_ID = teamPerson.PERSON_ID,
                                                    ORG_ID = filter.OrgId,
                                                };
                                                shiftDetailList.Add(schDetail);
                                            };
                                        }
                                    }
                                }
                            }
                            dayIndex++;
                        }
                        sh.CURR_TIME = perEndDay.AddDays(1);
                    }
                }
                //统一提交数据
                this.UnifiedCommit(() =>
                {
                    if (shiftList.Any())
                        this.BantchAddEntityNoCommit(shiftList);
                    if (shiftDetailList.Any())
                        this.BantchAddEntityNoCommit(shiftDetailList);
                    this.BantchUpdateEntityNoCommit(configData);
                });
                return true;
            });
        }

        private void GetCascaderOptions(List<ControlNodelModel> options, IEnumerable<TreeNode<T_FM_DEPARTMENT>> nodes)
        {
            foreach (var item in nodes)
            {
                if (item.Children.Any())
                {
                    options.Add(new ControlNodelModel { Value = item.Node.ID.ToString(), Label = item.Node.NAME });
                    GetCascaderOptions(options, item.Children);
                }
                else
                {
                    options.Add(new ControlNodelModel { Value = item.Node.ID.ToString(), Label = item.Node.NAME });
                }

            }
        }
    }
}
