using System;
using System.Collections.Generic;
using System.Linq;
using Siger.Middlelayer.Common;
using Siger.Middlelayer.Common.Helpers;
using Siger.Middlelayer.Common.ModuleEnum;
using Siger.Middlelayer.Log;
using Siger.Middlelayer.Repository.Repositories.Interface;
using Siger.Middlelayer.TpmRepository.Entities;
using Siger.Middlelayer.TpmRepository.Repositories.Interface;

namespace Siger.ApiTPM.Utilities
{
    public class RepairReportLevelHelper
    {
        private readonly int _projectId;
        private readonly IRepairRepository _repair;
        private readonly IRepairReportRepository _repairReport;
        private readonly IWorkingCalendarRepository _calendarRepository;
        private readonly ISigerProjectShiftRepository _projectShiftRepository;
        //private readonly IWorkingMachineSetRepository _machineSetRepository;
        private readonly IWorkingRelationMachineRepository _workingRelationMachine;
        private readonly IWorkingRelationUserRepository _workingRelationUser;
        public RepairReportLevelHelper(int projectId, IRepairRepository repair, IRepairReportRepository repairReport,
            IWorkingCalendarRepository calendarRepository, ISigerProjectShiftRepository projectShiftRepository, IWorkingRelationUserRepository workingRelationUser,IWorkingRelationMachineRepository workingRelationMachine)
        {
            _projectId = projectId;
            _repair = repair;
            _repairReport = repairReport;
            _calendarRepository = calendarRepository;
            _projectShiftRepository = projectShiftRepository;
            _workingRelationUser = workingRelationUser;
            _workingRelationMachine = workingRelationMachine;
            //_machineSetRepository = machineSetRepository;
        }

        public Dictionary<int, List<int>> GetReportPushAndSectionMidList(siger_project_repair repairInfo, int machineId,
            int time, int configRepeatTime, int level, int _projectId, int machinelevel)
        {
            var res = new Dictionary<int, List<int>>();
            var reportLevelMidList =
                GetReportLevelMidList(level, repairInfo.id, time, configRepeatTime, machinelevel).Where(t => t > 0)
                    .Distinct().ToList();

            var workgroupUsermidList = GetWorkgroupUsermidList(repairInfo, machineId, time).Where(t => t > 0).Distinct().ToList();
            res.Add((int) AppPushType.PushAndSave, reportLevelMidList);
            res.Add((int) AppPushType.SaveNotPush, workgroupUsermidList);
            return res;
        }

        /// <summary>
        /// 已知上报等级，获取通知列表
        /// </summary>
        /// <returns></returns>
        public List<int> GetReportLevelMidList(int templevel, int repairId, int time, int configRepeatTime, int machinelevel)
        {
            var midList = new List<int>();
            if (templevel > 0)
            {
                midList = _repairReport.ListLevelUser(_projectId, templevel, machinelevel).ToList();
                return midList;
            }

            var spaceTimesList = _repairReport
                .GetList(t => t.projectid == _projectId && t.status == (int)RowState.Valid && t.machinelevel == machinelevel).ToList();
            //获取上报等级
            templevel = GetRepairReportLevel(repairId, time, configRepeatTime, spaceTimesList);
            if (templevel > 0)
            {
                midList = _repairReport.ListLevelUser(_projectId, templevel, machinelevel).ToList();
            }
            return midList;
        }

        private List<int> GetWorkgroupUsermidList(siger_project_repair repairInfo, int machineid, int time)
        {
            var midList = new List<int>
            {
                repairInfo.mid,
                repairInfo.takemid,
                repairInfo.signmid,
                repairInfo.completemid,
                repairInfo.checkmid
            };
            var repairadd = _repair.GetAddUserListByRepairId(repairInfo.id).ToList();
            if (repairadd.Any())
            {
                midList.AddRange(repairadd.Select(t => t.mid).ToList());
            }

            var date = DateTime.Parse(UnixTimeHelper.ConvertIntDate(time));
            //var userMids = _machineSetRepository.GetList(q => q.machine_id == machineid && q.project_id == _projectId && q.status == (int)RowState.Valid).Select(q => q.user_mid)
            //    .Distinct().ToList();
            var machineRelation = _workingRelationMachine.Get(f => f.projectid ==_projectId && f.machine==machineid && f.status == (int)RowState.Valid);
            var userMids = machineRelation != null ? machineRelation.employsSplit : new List<int>();

            var cals = _calendarRepository.GetList(q => userMids.Contains(q.user_mid) && q.status == (int)RowState.Valid && q.date == date && q.machine_id == machineid).ToList();
            var allshifts = _projectShiftRepository.GetList(q => q.status == (int)RowState.Valid && q.projectid == _projectId);
           
            if (cals.Any())
            {
                var shiftids = cals.Select(m => m.shift_id).Distinct().ToList();
                var nowDate = UnixTimeHelper.GetUnixByDate(date.ToShortDateString());
                foreach (var calendar in cals)
                {
                    var shift = allshifts.FirstOrDefault(q => q.id == calendar.shift_id);
                    if (shift == null)
                    {
                        continue;
                    }

                    //零点到零点的，全部都算
                    if (shift.start_time == 0 && shift.end_time == 0)
                    {
                        midList.Add(calendar.user_mid);
                    }
                    //在时间范围内的
                    else if (nowDate + shift.start_time <= time && nowDate + shift.end_time >= time)
                    {
                        midList.Add(calendar.user_mid);
                    }
                    //结束时间小于开始时间
                    else if (shift.end_time <= shift.start_time)
                    {
                        if (nowDate + shift.start_time <= time && nowDate + 86400 + shift.end_time >= time)
                        {
                            midList.Add(calendar.user_mid);
                        }
                    }
                }
            }

            return midList.ToList();
        }

        /// <summary>
        /// 根据维修工单获取上报等级
        /// </summary>
        /// <param name="repairId">维修工单</param>
        /// <param name="time">当前时间</param>
        /// <param name="configRepeatTime">配置的重复推送时间</param>
        /// <param name="spaceTimeArr">配置的异常上报时间数据</param>
        /// <returns></returns>
        public int GetRepairReportLevel(int repairId, int time, int configRepeatTime,
            List<siger_project_repair_report> spaceTimeArr)
        {
            int templevel = 0;
            var repair = _repair.LevelByRepair(repairId, _projectId);
            if (repair != null)
            {
                if (spaceTimeArr.Any())
                {
                    var spaceTime4 = spaceTimeArr.FirstOrDefault(t => t.type == 1 && t.start_level == 3);
                    var spaceTime3 = spaceTimeArr.FirstOrDefault(t => t.type == 1 && t.start_level == 2);
                    var spaceTime2 = spaceTimeArr.FirstOrDefault(t => t.type == 1 && t.start_level == 1);
                    switch (repair.status)
                    {
                        case 1:
                            var difference = time - repair.createtime;
                            templevel = GetCompareTempLevel(difference, spaceTime4, spaceTime3, spaceTime2);
                            break;
                        case 2:
                            var difference1 = time - repair.createtime;
                            var difference2 = repair.taketime - repair.createtime;
                            difference = Math.Max(difference1, difference2);
                            templevel = GetCompareTempLevel(difference, spaceTime4, spaceTime3, spaceTime2);
                            break;
                        case 3:
                            difference1 = time - repair.createtime;
                            difference2 = repair.taketime - repair.createtime;
                            var difference3 = repair.signtime - repair.createtime;
                            difference = Math.Max(difference1, difference2);
                            difference = Math.Max(difference3, difference);
                            templevel = GetCompareTempLevel(difference, spaceTime4, spaceTime3, spaceTime2);
                            break;
                        case 4:
                            difference1 = time - repair.createtime;
                            difference2 = repair.taketime - repair.createtime;
                            difference3 = repair.signtime - repair.createtime;
                            var difference4 = repair.completetime - repair.createtime;
                            difference = Math.Max(difference1, difference2);
                            difference = Math.Max(difference3, difference);
                            difference = Math.Max(difference4, difference);
                            templevel = GetCompareTempLevel(difference, spaceTime4, spaceTime3, spaceTime2);
                            break;
                        case 5:
                            difference1 = time - repair.createtime;
                            difference2 = repair.taketime - repair.createtime;
                            difference3 = repair.signtime - repair.createtime;
                            difference4 = repair.completetime - repair.createtime;
                            var difference5 = repair.checktime - repair.createtime;
                            difference = Math.Max(difference1, difference2);
                            difference = Math.Max(difference3, difference);
                            difference = Math.Max(difference4, difference);
                            difference = Math.Max(difference5, difference);
                            templevel = GetCompareTempLevel(difference, spaceTime4, spaceTime3, spaceTime2);
                            break;
                    }
                }
            }

            return templevel;
        }

        private int GetCompareTempLevel(int difference, siger_project_repair_report spaceTime4,
            siger_project_repair_report spaceTime3, siger_project_repair_report spaceTime2)
        {
            int templevel;
            if (spaceTime4 != null && difference > spaceTime4.space_time)
            {
                templevel = 4;
            }
            else if (spaceTime3 != null && difference > spaceTime3.space_time)
            {
                templevel = 3;
            }
            else if (spaceTime2 != null && difference > spaceTime2.space_time)
            {
                templevel = 2;
            }
            else
            {
                //此时该工单未超时
                templevel = 1;
            }

            return templevel;
        }
    }
}
