using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Microsoft.AspNetCore.Mvc;
using Siger.ApiCommon.Result;
using Siger.Middlelayer.CncRepository.Entities;
using Siger.Middlelayer.CncRepository.Repositories.Interface;
using Siger.Middlelayer.CncRepository.Request;
using Siger.Middlelayer.CncRepository.Response;
using Siger.Middlelayer.Common;
using Siger.Middlelayer.Common.Extensions;
using Siger.Middlelayer.Common.Helpers;
using Siger.Middlelayer.Common.ModuleEnum;
using Siger.Middlelayer.Repository;
using Siger.Middlelayer.Repository.Repositories.Interface;
using Siger.Middlelayer.Repository.Request;
using Siger.Middlelayer.Log;
using NPOI.HSSF.Util;
using Siger.ApiCNC.Result;

namespace Siger.ApiCNC.Controllers
{
    public class InformationConfigurationController : BaseController
    {
        private readonly IUnitOfWork _unitOfWork;
        private readonly IProductionTimeAllocationRepository _timeAllocationRepository;
        private readonly ISigerProjectRestTypeRepository _restTypeRepository;
        private readonly IProductionTimeRepository _timeRepository;
        private readonly ISigerProjectUserRepository _userRepository;
        private readonly ISigerProjectMachineAttributionRepository _machineAttributionRepository;
        private readonly ISigerProjectMachineRepository _machineRepository;
        private readonly ISigerProjectShiftRepository _projectShiftRepository;
        public InformationConfigurationController(IUnitOfWork unitOfWork, IProductionTimeRepository timeRepository, ISigerProjectUserRepository userRepository,
            ISigerProjectMachineAttributionRepository machineAttributionRepository, ISigerProjectMachineRepository machineRepository,
            IProductionTimeAllocationRepository timeAllocationRepository, ISigerProjectRestTypeRepository restTypeRepository,
            ISigerProjectShiftRepository projectShiftRepository)
        {
            _unitOfWork = unitOfWork;
            _timeRepository = timeRepository;
            _userRepository = userRepository;
            _machineAttributionRepository = machineAttributionRepository;
            _machineRepository = machineRepository;
            _restTypeRepository = restTypeRepository;
            _timeAllocationRepository = timeAllocationRepository;
            _projectShiftRepository = projectShiftRepository;
        }
        /// <summary>
        /// 查
        /// </summary>
        /// <param name="page"></param>
        /// <param name="pageSige"></param>
        /// <returns></returns>
        [HttpGet]
        public IActionResult TimeAllSettingShow(int page, int pageSige)
        {
            var time = _timeAllocationRepository.GetTypeList(page, pageSige, ProjectId);
            foreach (var item in time.Data)
            {
                var users = _userRepository.Get(q => q.mid.ToString() == item.founder && q.status == (int)RowState.Valid && q.projectid == ProjectId);
                item.founder = users != null ? users.name : "";
            }
            return new PagedObjectResult(time.Data, time.Total, page, pageSige);
        }
        /// <summary>
        /// 根据guid查
        /// </summary>
        /// <param name="guid"></param>
        /// <returns></returns>
        [HttpGet]
        public IActionResult TimeAllSettingShows(string guid)
        {
            var type = new RequestSelectTimes();
            var sections = new List<int>();
            var time = _timeAllocationRepository.GetList(q => q.guid == guid && q.status == (int)RowState.Valid && q.projectid == ProjectId).ToList();
            if (time.Any())
            {
                foreach (var item in time)
                {
                    sections.Add(item.sectionid);
                }

                var users = _userRepository.Get(q => q.mid.ToString() == time.FirstOrDefault().founder && q.status == (int)RowState.Valid && q.projectid == ProjectId);
                var entity = new RequestSelectTime()
                {
                    guid = time.FirstOrDefault().guid,
                    add_time = time.FirstOrDefault().add_time,
                    founder = users != null ? users.name : "",
                    uid = time.FirstOrDefault().founder,
                    remark = time.FirstOrDefault().remark,
                    type = time.FirstOrDefault().type,
                    typeids = time.FirstOrDefault().typeids
                };
                type.sectionids = sections;
                type.type = entity;
            }
            return new ObjectResult(type);
        }


        [HttpGet]
        public IActionResult GetUsers(string keyword)
        {
            var users = _userRepository.GetList(q => q.status == (int)RowState.Valid && q.projectid == ProjectId)
                .Select(m => new
                {
                    id = m.mid,
                    text = m.name,
                });
            if (!string.IsNullOrWhiteSpace(keyword))
            {
                users = users.Where(q => q.text.Contains(keyword));
            }
            return new ObjectResult(users.ToList());
        }
        /// <summary>
        /// 增
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<IActionResult> TimeAllSetting([FromBody] RequestAddTimeAllSetting request)
        {
            if (!(request.sectionids.Count > 0))
            {
                throw new BadRequestException(RequestEnum.MachineNotFound);
            }
            if (request.typeids == "0")
            {
                throw new BadRequestException(RequestEnum.TimeTypeIsEmpty);
            }
            var nameList = _timeAllocationRepository.GetList(q => q.type == request.type && q.status == (int)RowState.Valid && q.projectid == ProjectId);
            if (nameList.Any())
            {
                throw new BadRequestException(RequestEnum.NameHasExist);
            }
            //判断重复
            var restlist = new List<RequestRests>();
            var str = request.typeids.Split(',');
            foreach (var item in str)
            {
                var rest = _restTypeRepository.Get(q => q.id.ToStr() == item && q.status == (int)RowState.Valid && q.projectid == ProjectId);
                if (rest != null)
                {
                    var rests = new RequestRests
                    {
                        start = rest.startTime,
                        range = rest.range,
                        end = rest.endTime
                    };
                    restlist.Add(rests);
                }
            }
            if (restlist.Any() && restlist.Count > 1)
            {
                var stare1 = 0.0;
                var end1 = 0.0;
                var stare2 = 0.0;
                var end2 = 0.0;
                for (int i = 0; i < restlist.Count - 1; i++)
                {
                    for (int j = i+1; j < restlist.Count; j++)
                    {

                        if ((restlist[i].range == restlist[j].range)&&restlist[i].range!= (int)TimeType.Holiday && restlist[j].range != (int)TimeType.Holiday)
                        {
                            if (UnixTimeHelper.GetUnixAllTime(restlist[i].start) <= UnixTimeHelper.GetUnixAllTime(restlist[i].end))
                            {
                                var time1 = "1979-01-01 " + restlist[i].start;
                                var time2 = "1979-01-01 " + restlist[i].end;
                                stare1 = UnixTimeHelper.ConvertDataTimeLong(time1.ToDateTime());
                                end1 = UnixTimeHelper.ConvertDataTimeLong(time2.ToDateTime());
                            }
                            else
                            {
                                var time1 = "1979-01-01 " + restlist[i].start;
                                var time2 = "1979-01-02 " + restlist[i].end;
                                stare1 = UnixTimeHelper.ConvertDataTimeLong(time1.ToDateTime());
                                end1 = UnixTimeHelper.ConvertDataTimeLong(time2.ToDateTime());
                            }
                            if (UnixTimeHelper.GetUnixAllTime(restlist[j].start) <= UnixTimeHelper.GetUnixAllTime(restlist[j].end))
                            {
                                var time1 = "1979-01-01 " + restlist[j].start;
                                var time2 = "1979-01-01 " + restlist[j].end;
                                stare2 = UnixTimeHelper.ConvertDataTimeLong(time1.ToDateTime());
                                end2 = UnixTimeHelper.ConvertDataTimeLong(time2.ToDateTime());
                            }
                            else
                            {
                                var time1 = "1979-01-01 " + restlist[j].start;
                                var time2 = "1979-01-02 " + restlist[j].end;
                                stare2 = UnixTimeHelper.ConvertDataTimeLong(time1.ToDateTime());
                                end2 = UnixTimeHelper.ConvertDataTimeLong(time2.ToDateTime());
                            }
                            if ((stare2 <= stare1 && end2 > stare1) || (stare2 < end1 && end2 >= end1)||(stare1>=stare2&& end1<=end2))
                            {
                                throw new BadRequestException(RequestEnum.ShiftTimeRangeError);
                            }
                        }

                        if (restlist[i].range == (int)TimeType.Holiday && restlist[j].range == (int)TimeType.Holiday)
                        {
                            DateTime.TryParse(restlist[i].start, out var time1);
                            DateTime.TryParse(restlist[i].end, out var time2);
                            DateTime.TryParse(restlist[j].start, out var time3);
                            DateTime.TryParse(restlist[j].end, out var time4);
                            stare1 = UnixTimeHelper.ConvertDataTimeLong(time1);
                            end1 = UnixTimeHelper.ConvertDataTimeLong(time2); 
                            stare2 = UnixTimeHelper.ConvertDataTimeLong(time3);
                            end2 = UnixTimeHelper.ConvertDataTimeLong(time4);
                            if ((stare2 <= stare1 && end2 > stare1) || (stare2 < end1 && end2 >= end1) || (stare1 >= stare2 && end1 <= end2))
                            {
                                throw new BadRequestException(RequestEnum.ShiftTimeRangeError);
                            }
                        }
                    }
                }
            }
            var guid = Guid.NewGuid().ToString();
            foreach (var item in request.sectionids)
            {
                var machines = _machineRepository.GetNCLevelSectionMachines(item, ProjectId);
                if (!machines.Any())
                {
                    throw new BadRequestException(RequestEnum.MachineNotFound);
                }
                var machineIds = machines.Select(m => m.machine_id).ToList();
                foreach (var machineId in machineIds)
                {
                    var section = _machineAttributionRepository.Get(t => t.projectid == ProjectId && t.status == (int)RowState.Valid &&
                        t.machine == machineId);
                    if (section == null)
                    {
                        continue;
                    }
                    var entity = new siger_project_production_time_allocation
                    {
                        type = request.type,
                        machineid = machineId,
                        sectionid = section.station,
                        founder = UserId.ToString(),
                        add_time = DateTime.Now,
                        projectid = ProjectId,
                        edit_time = DateTime.Now,
                        typeids = request.typeids,
                        remark = request.remark,
                        guid = guid
                    };
                    await _timeAllocationRepository.InsertAsync(entity);
                }
            }
            if (await _unitOfWork.CommitAsync() > 0)
            {
                return new ObjectResult(CommonEnum.Succefull);
            }
            throw new BadRequestException(CommonEnum.Fail);
        }
        /// <summary>
        /// 改
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        [HttpPost]
        public async Task<IActionResult> TimeAllSettingEdit([FromBody] RequestEditTimeAllSetting request)
        {
            var time = await _timeAllocationRepository.GetListAsync(q => q.guid == request.guid && q.status == (int)RowState.Valid && q.projectid == ProjectId);
            foreach (var item in time)
            {
                item.status = (int)RowState.Invalid;
                await _timeAllocationRepository.DeleteAsync(item);
            }
            if (!(request.sectionids.Count > 0))
            {
                throw new BadRequestException(RequestEnum.MachineNotFound);
            }
            var guid = Guid.NewGuid().ToString();
            foreach (var item in request.sectionids)
            {
                var machines = _machineRepository.GetNCLevelSectionMachines(item, ProjectId);
                if (!machines.Any())
                {
                    throw new BadRequestException(RequestEnum.MachineNotFound);
                }
                var machineIds = machines.Select(m => m.machine_id).ToList();
                foreach (var machineId in machineIds)
                {
                    var section = _machineAttributionRepository.Get(t => t.projectid == ProjectId && t.status == (int)RowState.Valid &&
                        t.machine == machineId);
                    if (section == null)
                    {
                        continue;
                    }
                    var entity = new siger_project_production_time_allocation
                    {
                        type = request.type,
                        machineid = machineId,
                        sectionid = section.station,
                        founder = request.uid,
                        add_time = request.add_time,
                        projectid = ProjectId,
                        edit_time = DateTime.Now,
                        typeids = request.typeids,
                        remark = request.remark,
                        guid = guid
                    };
                    await _timeAllocationRepository.InsertAsync(entity);
                }
            }
            if (await _unitOfWork.CommitAsync() > 0)
            {
                return new ObjectResult(CommonEnum.Succefull);
            }
            throw new BadRequestException(CommonEnum.Fail);
        }
        /// <summary>
        /// 删
        /// </summary>
        /// <param name="guid"></param>
        /// <returns></returns>
        [HttpGet]
        public async Task<IActionResult> TimeAllSettingDel(string guid)
        {
            var time = await _timeAllocationRepository.GetListAsync(q => q.guid == guid && q.status == (int)RowState.Valid && q.projectid == ProjectId);
            if (!time.Any())
            {
                throw new BadRequestException(CommonEnum.RecordNotFound);
            }
            foreach (var item in time)
            {
                item.status = (int)RowState.Invalid;
                await _timeAllocationRepository.UpdateAsync(item);
            }
            if (await _unitOfWork.CommitAsync() > 0)
            {
                return new ObjectResult(CommonEnum.Succefull);
            }
            throw new BadRequestException(CommonEnum.Fail);
        }

        [HttpPost]
        public IActionResult DeleteMultipleTimes([FromBody] RequestDeleteEntities request)
        {
            if (request.ids == null || !request.ids.Any())
            {
                throw new BadRequestException(RequestEnum.ParameterError);
            }

            var times = _timeRepository.GetList(q => request.ids.Contains(q.id) && q.projectid == ProjectId).ToList();
            foreach (var time in times)
            {
                time.status = (int)RowState.Invalid;
                _timeRepository.Update(time);
            }

            if (_unitOfWork.Commit() > 0)
            {
                return new ObjectResult(CommonEnum.Succefull);
            }
            throw new BadRequestException(CommonEnum.Fail);
        }

        /// <summary>
        /// 计划停机时间
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        [HttpPost]
        public IActionResult ScheduledDownTime([FromBody] RequestScheduledDownTime request)
        {
            var timeList = new List<int>();
            var times =_timeAllocationRepository.GetList(q => q.sectionid == request.sectionID && q.status == (int)RowState.Valid && q.projectid == ProjectId).ToList();

            var list = times.Select(q => q.guid).Distinct().ToList();
            if (times.Any())
            {
                foreach (var item in list)
                {
                    var time = times.Where(q => q.guid == item).FirstOrDefault();
                    var type = time.typeids.Split(',');
                    if (type.Length > 1)
                    {
                        for (int i = 0; i < type.Length; i++)
                        {
                            timeList.Add(type[i].ToInt());
                        }

                    }
                    else
                    {
                        timeList.Add(type[0].ToInt());
                    }
                }
            }
            if (!DateTime.TryParse(request.startTime, out var dtStart))
            {
                throw new ServerException(500146);
            }
            if (!DateTime.TryParse(dtStart.AddDays(1).AddSeconds(-1).ToString(), out var dtEnd))
            {
                throw new ServerException(500146);
            }
            var freStart = dtStart;
            var freEnd = dtEnd;
            var time5 = 0.0;
            var time6 = 0.0;
            if (request.frequency > 0)
            {

                var frequency = _projectShiftRepository.Get(q => q.id == request.frequency && q.status == (int)RowState.Valid && q.projectid == ProjectId);
                var starts = UnixTimeHelper.GetTimeByUnix(frequency.start_time);
                var ends = UnixTimeHelper.GetTimeByUnix(frequency.end_time);
                if (frequency.start_time < frequency.end_time)
                {
                    var sta = dtStart.ToString(ParameterConstant.DateFormat) + " " + starts;
                    var endd = dtEnd.ToString(ParameterConstant.DateFormat) + " " + ends;
                    DateTime.TryParse(sta, out  freStart);
                    DateTime.TryParse(endd, out  freEnd);
                    time5 = UnixTimeHelper.ConvertDataTimeLong(freStart);
                    time6 = UnixTimeHelper.ConvertDataTimeLong(freEnd);
                }
                else
                {
                    var sta = dtStart.ToString(ParameterConstant.DateFormat) + " " + starts;
                    var endd = dtStart.AddDays(1).ToString(ParameterConstant.DateFormat) + " " + ends;
                    DateTime.TryParse(endd, out  freEnd);
                    DateTime.TryParse(sta, out  freStart);
                    time5 = UnixTimeHelper.ConvertDataTimeLong(freStart);
                    time6 = UnixTimeHelper.ConvertDataTimeLong(freEnd);
                }
            }
            
            var timeLists = new RequestShiftLists();
            var shiftList = new List<RequestShiftList>();
            var timeOne = 0.0;//停机时长
            var timeTwo = 0.0;//运行时长
            var week = (int)DateTime.Parse(request.startTime).DayOfWeek;
            if (timeList.Any())
            {
                foreach (var item in timeList)
                {
                    var time3 = 0.0;
                    var time4 = 0.0;
                   
                    var shifts = new RequestShiftList();
                    var shift = _restTypeRepository.Get(q => q.id == item && q.status == (int)RowState.Valid && q.projectid == ProjectId);
                    if (shift != null)
                    {
                        if (request.frequency>0)
                        {
                            if (shift.range!= (int)TimeType.Holiday && shift.range == (week != 0 ? week : 7))
                            {
                                var time1 = dtStart.ToString(ParameterConstant.DateFormat) + " " + shift.startTime;
                                var time2 = dtStart.ToString(ParameterConstant.DateFormat) + " " + shift.endTime;
                                DateTime.TryParse(time1, out var startTime);
                                DateTime.TryParse(time2, out var endTime);
                                time3 = UnixTimeHelper.ConvertDataTimeLong(startTime);
                                time4 = UnixTimeHelper.ConvertDataTimeLong(endTime);
                               
                                if ((time5 <= time3 && time6 > time3) || (time5 < time4 && time6 >= time4) || (time3 >= time5 && time4 <= time6))
                                {
                                    shifts.startTime = shift.startTime;
                                    shifts.endTime = shift.endTime;
                                    timeOne += Math.Round((double)(UnixTimeHelper.ConvertDataTimeLong(shift.endTime) - UnixTimeHelper.ConvertDataTimeLong(shift.startTime.ToDateTime())) / 60, 2);
                                    shifts.duration = Math.Round((double)(UnixTimeHelper.ConvertDataTimeLong(shift.endTime) - UnixTimeHelper.ConvertDataTimeLong(shift.startTime.ToDateTime())) / 60, 2).ToString();
                                    shifts.title = shift.name;
                                    shiftList.Add(shifts);
                                }
                            }
                            if(shift.range == (int)TimeType.Holiday)
                            {
                                DateTime.TryParse(shift.startTime, out var startTime);
                                DateTime.TryParse(shift.endTime, out var endTime);
                                time3 = UnixTimeHelper.ConvertDataTimeLong(startTime);
                                time4 = UnixTimeHelper.ConvertDataTimeLong(endTime);
                                
                                if ((time5 <= time3 && time6 > time3) || (time5 < time4 && time6 >= time4) || (time3 >= time5 && time4 <= time6))
                                {
                                    shifts.startTime = shift.startTime;
                                    shifts.endTime = shift.endTime;
                                    timeOne += Math.Round((double)(UnixTimeHelper.ConvertDataTimeLong(shift.endTime) - UnixTimeHelper.ConvertDataTimeLong(shift.startTime.ToDateTime())) / 60, 2);
                                    shifts.duration = Math.Round((double)(UnixTimeHelper.ConvertDataTimeLong(shift.endTime) - UnixTimeHelper.ConvertDataTimeLong(shift.startTime.ToDateTime())) / 60, 2).ToString();
                                    shifts.title = shift.name;
                                    shiftList.Add(shifts);
                                }
                            } 
                        }
                        else
                        {

                            
                            if (shift.range== (week!=0?week:7))
                            {
                                shifts.startTime = shift.startTime;
                                shifts.endTime = shift.endTime;
                                timeOne += Math.Round((double)(UnixTimeHelper.ConvertDataTimeLong(shift.endTime) - UnixTimeHelper.ConvertDataTimeLong(shift.startTime.ToDateTime())) / 60, 2);
                                shifts.duration = Math.Round((double)(UnixTimeHelper.ConvertDataTimeLong(shift.endTime) - UnixTimeHelper.ConvertDataTimeLong(shift.startTime.ToDateTime())) / 60, 2).ToString();
                                shifts.title = shift.name;
                                shiftList.Add(shifts);
                            }
                            if (shift.range == (int)TimeType.Holiday)
                            {
                                shifts.startTime = shift.startTime;
                                shifts.endTime = shift.endTime;
                                timeOne += Math.Round((double)(UnixTimeHelper.ConvertDataTimeLong(shift.endTime) - UnixTimeHelper.ConvertDataTimeLong(shift.startTime.ToDateTime())) / 60, 2);
                                shifts.duration = Math.Round((double)(UnixTimeHelper.ConvertDataTimeLong(shift.endTime) - UnixTimeHelper.ConvertDataTimeLong(shift.startTime.ToDateTime())) / 60, 2).ToString();
                                shifts.title = shift.name;
                                shiftList.Add(shifts);
                            }
                        }
                        
                    }

                }
            }
            timeTwo = 24 * 60 - timeOne;
            timeLists.list = shiftList;
            timeLists.timeOne = timeOne.ToString();
            timeLists.timeTwo = timeTwo.ToString();
            return new ObjectResult(timeLists);
        }
    }

}