using AutoMapper;
using Microsoft.Extensions.Logging;
using Performance.DtoModels;
using Performance.EntityModels;
using Performance.EntityModels.Entity;
using Performance.EntityModels.Other;
using Performance.Infrastructure;
using Performance.Repository;
using Performance.Repository.Repository;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;

namespace Performance.Services
{
    public class AttendanceService : IAutoInjection
    {
        private readonly IMapper mapper;
        private readonly ILogger<AttendanceService> logger;
        private readonly PerforPerallotRepository perforPerallotRepository;
        private readonly PerforPerAttendanceRepository perforPerAttendanceRepository;
        private readonly PerfoPperAttendanceTypeRepository perfoPperAttendanceTypeRepository;
        private readonly PerfoPperAttendanceVacationeRepository perfoPperAttendanceVacationeRepository;
        private readonly PerforPerdeptdicRepository perdeptdicRepository;
        private readonly PerforPeremployeeRepository perforPeremployeeRepository;

        public AttendanceService(
            IMapper mapper,
            ILogger<AttendanceService> logger,
            PerforPerallotRepository perforPerallotRepository,
            PerforPerAttendanceRepository perforPerAttendanceRepository,
            PerfoPperAttendanceTypeRepository perfoPperAttendanceTypeRepository,
            PerfoPperAttendanceVacationeRepository perfoPperAttendanceVacationeRepository,
            PerforPerdeptdicRepository perdeptdicRepository,
            PerforPeremployeeRepository perforPeremployeeRepository)
        {
            this.mapper = mapper;
            this.logger = logger;
            this.perforPerallotRepository = perforPerallotRepository;
            this.perforPerAttendanceRepository = perforPerAttendanceRepository;
            this.perfoPperAttendanceTypeRepository = perfoPperAttendanceTypeRepository;
            this.perfoPperAttendanceVacationeRepository = perfoPperAttendanceVacationeRepository;
            this.perdeptdicRepository = perdeptdicRepository;
            this.perforPeremployeeRepository = perforPeremployeeRepository;
        }

        #region 初始考勤页面
        public ApiResponse<List<AttendanceStatistics>> GetAttendance(int allotId)
        {
            var allot = perforPerallotRepository.GetEntity(w => w.ID == allotId);
            if (allot == null)
                throw new PerformanceException("当前绩效记录不存在");

            var attendanceData = perforPerallotRepository.GetAttendance(allotId);


            List<AttendanceStatistics> statistics = new List<AttendanceStatistics>();
            // 交叉补全科室结束时间
            foreach (var personnelNumber in attendanceData.Select(w => w.PersonnelNumber).Distinct())
            {
                var attendances = attendanceData.Where(w => w.PersonnelNumber == personnelNumber).OrderBy(w => w.AttendanceDate);
                for (int i = 0; i < attendances.Count() - 1; i++)
                {
                    var begDate = attendances.ElementAt(i).AttendanceDate.Value.Date;
                    var endDate = attendances.ElementAt(i + 1).AttendanceDate.Value.Date;
                    // 调入科室需要额外减去1天作为上一个科室结束时间
                    var days = attendances.ElementAt(i + 1).Source == Attendance.Type.调入.ToString() ? -1 : 0;
                    if (endDate > begDate)
                    {
                        var stat = new AttendanceStatistics
                        {
                            AllotID = attendances.ElementAt(i).ALLOTID,
                            UnitType = attendances.ElementAt(i).UnitType,
                            AccountingUnit = attendances.ElementAt(i).AccountingUnit,
                            Department = attendances.ElementAt(i).Department,
                            PersonnelNumber = attendances.ElementAt(i).PersonnelNumber,
                            PersonnelName = attendances.ElementAt(i).PersonnelName,
                            BeginDate = begDate,
                            EndDate = endDate.AddDays(days),
                            Detial = new List<AttendanceStatisticsDetial>()
                        };
                        statistics.Add(stat);
                    }
                }
            }

            if (statistics != null)
                return new ApiResponse<List<AttendanceStatistics>>(ResponseType.OK, statistics);
            else
            {
                return new ApiResponse<List<AttendanceStatistics>>(ResponseType.Fail);
            }
        }


        #endregion

        #region 调入记录
        public ApiResponse<List<view_attendance>> GetCallIn(int allotId)
        {
            var view_attendance = perforPerallotRepository.GetAttendance(allotId).Where(t => t.Source.Contains("调入")).ToList();

            if (view_attendance != null)
                return new ApiResponse<List<view_attendance>>(ResponseType.OK, view_attendance);
            else
            {
                return new ApiResponse<List<view_attendance>>(ResponseType.Fail);
            }

        }
        public HandsonTable GetBatchCallInHandsonTable()
        {
            HandsonTable handson = new HandsonTable((int)SheetType.Unidentifiable, Person.Select(c => c.Item2).ToArray(), Person.Select(t => new collect_permission
            {
                HeadName = t.Item2,
                Visible = 1,
                Readnoly = 0
            }).ToList());
            if (handson.Columns != null && handson.Columns.Any())
            {
                foreach (var column in handson.Columns)
                {
                    column.Type = "text";
                    if (column.Data == "调入组别")
                    {
                        column.Source = EnumHelper.GetItems<UnitType>().Select(w => w.Description.Replace("行政后勤", "行政工勤")).ToArray();
                        column.Strict = true;
                    }

                    if (column.Data == "调入核算单元")
                    {
                        column.Source = EnumHelper.GetItems<AccountUnitType>().Where(w => w.Description != "").Select(w => w.Description).ToArray();
                        column.Strict = true;
                    }
                }
            }
            return handson;
        }

        public ApiResponse BatchCallIn(int allotId, int hospitalId, SaveCollectData request)
        {
            var dict = new Dictionary<string, string>();
            Person.ForEach(t => dict.Add(t.Item1, t.Item2));

            var dicData = CreateDataRow(request, dict);
            if (dicData == null || dicData.Count == 0)
                return new ApiResponse(ResponseType.Error, "空数据，无效操作");

            var jsons = JsonHelper.Serialize(dicData);
            var newAttendanceVacatione = JsonHelper.Deserialize<List<per_attendance>>(jsons);
            var oldCallinAttendance = perforPerAttendanceRepository.GetEntities(t => t.AllotId == allotId && t.HospitalId == hospitalId);

            var per_allot = perforPerallotRepository.GetEntities(t => t.ID == allotId && t.HospitalId == hospitalId).FirstOrDefault();

            if (per_allot == null) return new ApiResponse(ResponseType.Error, "无绩效数据");

            var per_dept_dic = perdeptdicRepository.GetEntities(t => t.HospitalId == hospitalId);
            var per_employee = perforPeremployeeRepository.GetEntities(t => t.AllotId == allotId && t.HospitalId == hospitalId);

            List<Dictionary<string, string>> error = new List<Dictionary<string, string>>();

            for (int i = 0; i < newAttendanceVacatione.Count; i++)
            {

                if (string.IsNullOrEmpty(newAttendanceVacatione[i].PersonnelName?.Trim())
                    || string.IsNullOrEmpty(newAttendanceVacatione[i].PersonnelNumber?.Trim())
                    || string.IsNullOrEmpty(newAttendanceVacatione[i].CallInAccountingUnit?.Trim())
                    || string.IsNullOrEmpty(newAttendanceVacatione[i].CallInUnitType?.Trim())
                    || newAttendanceVacatione[i].CallInDate == null)
                {
                    error.Add(new Dictionary<string, string>
                    {
                        { "行号", $"第{i+1}行" },
                        { "人员工号", newAttendanceVacatione[i].PersonnelNumber??"" },
                        { "人员姓名", newAttendanceVacatione[i].PersonnelName??"" },
                        { "调入核算单元", newAttendanceVacatione[i].CallInAccountingUnit??"" },
                        { "调入组别", newAttendanceVacatione[i].CallInUnitType??"" },
                        { "调入时间", newAttendanceVacatione[i].CallInDate.ToString()??"" },
                        { "来源", "粘贴数据" },
                        { "错误原因", "“关键信息缺失”请补全或删除" },
                    });
                }
                DateTime dt = new DateTime(per_allot.Year, per_allot.Month, 1).AddMonths(1);
                if (newAttendanceVacatione[i].CallInDate > dt)
                {
                    error.Add(new Dictionary<string, string>
                    {
                        { "行号", $"第{i+1}行" },
                        { "人员工号", newAttendanceVacatione[i].PersonnelNumber??"" },
                        { "人员姓名", newAttendanceVacatione[i].PersonnelName??"" },
                        { "调入核算单元", newAttendanceVacatione[i].CallInAccountingUnit??"" },
                        { "调入组别", newAttendanceVacatione[i].CallInUnitType??"" },
                        { "调入时间", newAttendanceVacatione[i].CallInDate.ToString()??"" },
                        { "来源", "粘贴数据" },
                        { "错误原因", "调入时间不在当前绩效月份范围内" },
                    });
                }


                if (newAttendanceVacatione[i].CallInUnitType != per_dept_dic.FirstOrDefault(t => t.AccountingUnit == newAttendanceVacatione[i].CallInAccountingUnit)?.UnitType)
                {
                    error.Add(new Dictionary<string, string>
                    {
                        { "行号", $"第{i+1}行" },
                        { "人员工号", newAttendanceVacatione[i].PersonnelNumber??"" },
                        { "人员姓名", newAttendanceVacatione[i].PersonnelName??"" },
                        { "调入核算单元", newAttendanceVacatione[i].CallInAccountingUnit??"" },
                        { "调入组别", newAttendanceVacatione[i].CallInUnitType??"" },
                        { "调入时间", newAttendanceVacatione[i].CallInDate.ToString()??"" },
                        { "来源", "粘贴数据" },
                        { "错误原因", "该核算单元的调入组别不一致或不存在" },
                    });
                }

                if (newAttendanceVacatione[i].PersonnelName != per_employee.FirstOrDefault(t => t.PersonnelNumber == newAttendanceVacatione[i].PersonnelNumber && t.AllotId == allotId && t.HospitalId == hospitalId)?.DoctorName)
                {
                    error.Add(new Dictionary<string, string>
                    {
                        { "行号", $"第{i+1}行" },
                        { "人员工号", newAttendanceVacatione[i].PersonnelNumber??"" },
                        { "人员姓名", newAttendanceVacatione[i].PersonnelName??"" },
                        { "调入核算单元", newAttendanceVacatione[i].CallInAccountingUnit??"" },
                        { "调入组别", newAttendanceVacatione[i].CallInUnitType??"" },
                        { "调入时间", newAttendanceVacatione[i].CallInDate.ToString()??"" },
                        { "来源", "粘贴数据" },
                        { "错误原因", "该人员与人员字典不一致或不存在" },
                    });
                }
                var oldEmp = oldCallinAttendance.FirstOrDefault(w => w.PersonnelNumber == newAttendanceVacatione[i].PersonnelNumber);
                if (!string.IsNullOrEmpty(newAttendanceVacatione[i].PersonnelName) && oldEmp != null && oldEmp.PersonnelName != newAttendanceVacatione[i].PersonnelName)
                {
                    error.Add(new Dictionary<string, string>
                    {
                        { "行号", $"第{i+1}行" },
                        { "人员工号", newAttendanceVacatione[i].PersonnelNumber??"" },
                        { "人员姓名", newAttendanceVacatione[i].PersonnelName??"" },
                        { "调入核算单元", newAttendanceVacatione[i].CallInAccountingUnit??"" },
                        { "调入组别", newAttendanceVacatione[i].CallInUnitType??"" },
                        { "调入时间", newAttendanceVacatione[i].CallInDate.ToString()??"" },
                        { "来源", "“粘贴数据”与“历史数据”比对" },
                        { "错误原因", $"原名“{oldEmp.PersonnelName}”,工号相同但姓名不同,请删除“历史数据”中该员工" },
                    });
                }
            }
            if (error.Count > 0)
                return new ApiResponse(ResponseType.WarningTable, "验证不通过,当前操作已拒绝", error);

            List<per_attendance> addPer_Attendances = new List<per_attendance>();
            List<per_attendance> deletePer_Attendances = new List<per_attendance>();

            foreach (var data in newAttendanceVacatione)
            {
                data.AllotId = allotId;
                data.HospitalId = hospitalId;
                addPer_Attendances.Add(data);
                var any = oldCallinAttendance.FirstOrDefault(w => w.AllotId == allotId && w.HospitalId == hospitalId && w.CallInDate == data.CallInDate && w.CallInAccountingUnit?.Trim() == data.CallInAccountingUnit?.Trim() && w.CallInUnitType?.Trim() == data.CallInUnitType?.Trim() && w.PersonnelName?.Trim() == data.PersonnelName?.Trim() && w.PersonnelNumber?.Trim() == data.PersonnelNumber?.Trim());
                if (any != null) deletePer_Attendances.Add(any);
            }

            if (deletePer_Attendances != null && deletePer_Attendances.Any())
                perforPerAttendanceRepository.RemoveRange(deletePer_Attendances.ToArray());
            if (addPer_Attendances != null && addPer_Attendances.Any())
                perforPerAttendanceRepository.AddRange(addPer_Attendances.ToArray());

            return new ApiResponse(ResponseType.OK, "");

        }

        #endregion

        #region 考勤类型

        public ApiResponse<List<per_attendance_type>> GetAttendanceType(int allotId, int hospitalId)
        {
            var result = perfoPperAttendanceTypeRepository.GetEntities(t => t.AllotId == allotId && t.HospitalId == hospitalId).ToList();
            if(result != null)
            return new ApiResponse<List<per_attendance_type>>(ResponseType.OK, result);
            else
            {
                return new ApiResponse<List<per_attendance_type>>(ResponseType.Fail);

            }
        }
        public ApiResponse<AttendanceType> InsertAttendanceType(int allotId, int hospitalId, AttendanceType attendanceType)
        {
            var any = perfoPperAttendanceTypeRepository.GetEntities().FirstOrDefault(t => t.AllotId == allotId && t.HospitalId == hospitalId && t.AttendanceName == attendanceType.AttendanceName);
            if (any != null)
            {
                any.IsDeduction = Convert.ToInt32(attendanceType.IsDeduction);
                if (perfoPperAttendanceTypeRepository.Update(any)) return new ApiResponse<AttendanceType>(ResponseType.OK, "修改成功");
                else return new ApiResponse<AttendanceType>(ResponseType.Fail, "修改失败");

            }
            else
            {
                per_attendance_type per_Attendance_Type = new per_attendance_type()
                {
                    AllotId = allotId,
                    HospitalId = hospitalId,
                    AttendanceName = attendanceType.AttendanceName,
                    IsDeduction = Convert.ToInt32(attendanceType.IsDeduction)
                };
                if (perfoPperAttendanceTypeRepository.Add(per_Attendance_Type)) return new ApiResponse<AttendanceType>(ResponseType.OK, "添加成功");
                else return new ApiResponse<AttendanceType>(ResponseType.Fail, "添加失败");
            }

        }
        public ApiResponse DeleteAttendanceType(int id)
        {
            var any = perfoPperAttendanceTypeRepository.GetEntities().FirstOrDefault(t => t.Id == id);

            var use = perfoPperAttendanceVacationeRepository.GetEntities().FirstOrDefault(t => t.TypeId == any.Id);
            if (any != null && use == null)
            {
                if (perfoPperAttendanceTypeRepository.DeleteFromQuery(t => t.Id == id) > 0) return new ApiResponse(ResponseType.OK, "删除成功");
                else return new ApiResponse(ResponseType.Fail, "删除失败");
            }
            else return new ApiResponse(ResponseType.Fail, "删除失败");
        }
        #endregion

        #region 考勤记录
        public HandsonTable GetAttendanceVacationHandsonTable()
        {
            HandsonTable handson = new HandsonTable((int)SheetType.Unidentifiable, Vacation.Select(c => c.Item2).ToArray(), Vacation.Select(t => new collect_permission
            {
                HeadName = t.Item2,
                Visible = 1,
                Readnoly = 0
            }).ToList());
            if (handson.Columns != null && handson.Columns.Any())
            {
                foreach (var column in handson.Columns)
                {
                    column.Type = "text";
                    if (column.Data.Contains("时间"))
                    {
                        column.Type = "DateFormat";
                        column.DateFormat = "YYYY/MM/DD";
                    }
                    if (column.Data == "考勤类型")
                    {
                        column.Source = perfoPperAttendanceTypeRepository.GetEntities().Select(t => t.AttendanceName).ToArray();
                    }
                }
            }
            return handson;
        }

        public ApiResponse<List<RecordAttendcance>> GetAttendanceVacation(int allotId, int hospitalId)
        {
            var vacatione = perfoPperAttendanceVacationeRepository.GetEntities(t => t.AllotId == allotId && t.HospitalId == hospitalId);
            var type = perfoPperAttendanceTypeRepository.GetEntities(t => t.AllotId == allotId && t.HospitalId == hospitalId);

            var data = from a in vacatione
                       join b in type on a.TypeId equals b.Id into temp
                       from tt in temp.DefaultIfEmpty()
                       select new RecordAttendcance
                       {
                           Id = a.Id,
                           AllotId = a.AllotId,
                           HospitalId = a.HospitalId,
                           PersonnelName = a.PersonnelName,
                           PersonnelNumber = a.PersonnelNumber,
                           AttendanceName = tt.AttendanceName,
                           TypeId = a.TypeId,
                           BegDate = a.BegDate,
                           EndDate = a.EndDate,
                           Days = Convert.ToInt32(new TimeSpan(Convert.ToDateTime(a.BegDate).Ticks).Subtract(new TimeSpan(Convert.ToDateTime(a.EndDate).Ticks)).Duration().Days) + 1
                       };

            if (data != null)
                return new ApiResponse<List<RecordAttendcance>>(ResponseType.OK, data.ToList());
            else
            {
                return new ApiResponse<List<RecordAttendcance>>(ResponseType.Fail);

            }

        }

        public ApiResponse AttendanceBatch(int allotId, int hospitalId, SaveCollectData request)
        {
            var dict = new Dictionary<string, string>();
            Vacation.ForEach(t => dict.Add(t.Item1, t.Item2));

            var dicData = CreateDataRow(request, dict);
            if (dicData == null || dicData.Count == 0)
                return new ApiResponse(ResponseType.Error, "空数据，无效操作");

            var jsons = JsonHelper.Serialize(dicData);
            var newAttendanceVacatione = JsonHelper.Deserialize<List<RecordAttendcance>>(jsons);
            var oldAttendanceVacatione = perfoPperAttendanceVacationeRepository.GetEntities(t => t.AllotId == allotId && t.HospitalId == hospitalId);

            var attendanceType = perfoPperAttendanceTypeRepository.GetEntities();
            var per_employee = perforPeremployeeRepository.GetEntities(t => t.AllotId == allotId && t.HospitalId == hospitalId);

            List<Dictionary<string, string>> error = new List<Dictionary<string, string>>();
            var per_allot = perforPerallotRepository.GetEntities(t => t.ID == allotId && t.HospitalId == hospitalId).FirstOrDefault();

            for (int i = 0; i < newAttendanceVacatione.Count; i++)
            {

                if (string.IsNullOrEmpty(newAttendanceVacatione[i].PersonnelName?.Trim())
                    || string.IsNullOrEmpty(newAttendanceVacatione[i].PersonnelNumber?.Trim())
                    || string.IsNullOrEmpty(newAttendanceVacatione[i].AttendanceName?.Trim())
                    || newAttendanceVacatione[i].BegDate == null
                    || newAttendanceVacatione[i].EndDate == null)
                {
                    error.Add(new Dictionary<string, string>
                    {
                        { "行号", $"第{i+1}行" },
                        { "人员工号", newAttendanceVacatione[i].PersonnelNumber??"" },
                        { "人员姓名", newAttendanceVacatione[i].PersonnelName??"" },
                        { "考勤类型", newAttendanceVacatione[i].AttendanceName??"" },
                        { "开始日期", newAttendanceVacatione[i].BegDate.ToString()??"" },
                        { "结束日期", newAttendanceVacatione[i].EndDate.ToString()??"" },
                        { "来源", "粘贴数据" },
                        { "错误原因", "“关键信息缺失”请补全或删除" },
                    });
                }

                var typeAny = attendanceType.Where(t => t.AttendanceName.Contains(newAttendanceVacatione[i].AttendanceName));
                if (typeAny == null || !typeAny.Any())
                {
                    error.Add(new Dictionary<string, string>
                    {
                        { "行号", $"第{i+1}行" },
                        { "人员工号", newAttendanceVacatione[i].PersonnelNumber??"" },
                        { "人员姓名", newAttendanceVacatione[i].PersonnelName??"" },
                        { "考勤类型", newAttendanceVacatione[i].AttendanceName??"" },
                        { "开始日期", newAttendanceVacatione[i].BegDate.ToString()??"" },
                        { "结束日期", newAttendanceVacatione[i].EndDate.ToString()??"" },
                        { "来源", "粘贴数据" },
                        { "错误原因", "没有该考勤类型" },
                    });
                }
                if (newAttendanceVacatione[i].PersonnelName != per_employee.FirstOrDefault(t => t.PersonnelNumber == newAttendanceVacatione[i].PersonnelNumber && t.AllotId == allotId && t.HospitalId == hospitalId)?.DoctorName)
                {
                    error.Add(new Dictionary<string, string>
                    {
                        { "行号", $"第{i+1}行" },
                        { "人员工号", newAttendanceVacatione[i].PersonnelNumber??"" },
                        { "人员姓名", newAttendanceVacatione[i].PersonnelName??"" },
                        { "考勤类型", newAttendanceVacatione[i].AttendanceName??"" },
                        { "开始日期", newAttendanceVacatione[i].BegDate.ToString()??"" },
                        { "结束日期", newAttendanceVacatione[i].EndDate.ToString()??"" },
                        { "来源", "粘贴数据" },
                        { "错误原因", "该人员与人员字典不一致或不存在" },
                    });
                }
                var oldEmp = oldAttendanceVacatione.FirstOrDefault(w => w.PersonnelNumber == newAttendanceVacatione[i].PersonnelNumber);
                if (!string.IsNullOrEmpty(newAttendanceVacatione[i].PersonnelName) && oldEmp != null && oldEmp.PersonnelName != newAttendanceVacatione[i].PersonnelName)
                {
                    error.Add(new Dictionary<string, string>
                    {
                        { "行号", $"第{i+1}行" },
                        { "人员工号", newAttendanceVacatione[i].PersonnelNumber??"" },
                        { "人员姓名", newAttendanceVacatione[i].PersonnelName??"" },
                        { "考勤类型", newAttendanceVacatione[i].AttendanceName??"" },
                        { "开始日期", newAttendanceVacatione[i].BegDate.ToString()??"" },
                        { "结束日期", newAttendanceVacatione[i].EndDate.ToString()??"" },
                        { "来源", "“粘贴数据”与“历史数据”比对" },
                        { "错误原因", $"原名“{oldEmp.PersonnelName}”,工号相同但姓名不同,请删除“历史数据”中该员工" },
                    });

                }

                DateTime dt = new DateTime(per_allot.Year, per_allot.Month, 1);
                if (newAttendanceVacatione[i].BegDate >= dt && newAttendanceVacatione[i].EndDate > dt.AddMonths(1))
                {
                    error.Add(new Dictionary<string, string>
                    {
                        { "行号", $"第{i+1}行" },
                        { "人员工号", newAttendanceVacatione[i].PersonnelNumber??"" },
                        { "人员姓名", newAttendanceVacatione[i].PersonnelName??"" },
                        { "考勤类型", newAttendanceVacatione[i].AttendanceName??"" },
                        { "开始日期", newAttendanceVacatione[i].BegDate.ToString()??"" },
                        { "结束日期", newAttendanceVacatione[i].EndDate.ToString()??"" },
                        { "来源", "粘贴数据" },
                        { "错误原因", "考勤时间不在该绩效月份内" },
                    });
                }

                var newDate = SplitEveryDay(Convert.ToDateTime(newAttendanceVacatione[i].BegDate), Convert.ToDateTime(newAttendanceVacatione[i].EndDate));

                foreach (var item in oldAttendanceVacatione.Where(w => w.PersonnelNumber == newAttendanceVacatione[i].PersonnelNumber))
                {
                    var oldDate = SplitEveryDay(Convert.ToDateTime(item.BegDate), Convert.ToDateTime(item.EndDate));

                    bool any = false;
                    foreach (var old in oldDate)
                    {
                        if (newDate.Contains(old))
                            any = true;


                    }
                    if(any)
                    error.Add(new Dictionary<string, string>
                        {
                        { "行号", $"第{i+1}行" },
                        { "人员工号", newAttendanceVacatione[i].PersonnelNumber??"" },
                        { "人员姓名", newAttendanceVacatione[i].PersonnelName??"" },
                        { "考勤类型", newAttendanceVacatione[i].AttendanceName??"" },
                        { "开始日期", newAttendanceVacatione[i].BegDate.ToString()??"" },
                        { "结束日期", newAttendanceVacatione[i].EndDate.ToString()??"" },
                        { "来源", "粘贴数据" },
                        { "错误原因", "该考勤时间范围与历史考勤时间冲突" },
                        });
                }
            }
            if (error.Count > 0)
                return new ApiResponse(ResponseType.WarningTable, "验证不通过,当前操作已拒绝", error);

            List<per_attendance_vacation> addAttendanceVacatione = new List<per_attendance_vacation>();
            List<per_attendance_vacation> deleteAttendanceVacatione = new List<per_attendance_vacation>();

            var type = GetAttendanceType(allotId, hospitalId);
            foreach (var data in newAttendanceVacatione)
            {
                data.AllotId = allotId;
                data.HospitalId = hospitalId;
                data.TypeId = type.Data.FirstOrDefault(t => t.AttendanceName == data.AttendanceName).Id;
                addAttendanceVacatione.Add(data);
                var any = oldAttendanceVacatione.FirstOrDefault(w => w.AllotId == allotId && w.HospitalId == hospitalId && w.BegDate == data.BegDate && w.EndDate == data.EndDate && w.PersonnelName?.Trim() == data.PersonnelName?.Trim() && w.PersonnelNumber?.Trim() == data.PersonnelNumber?.Trim() && w.TypeId == data.TypeId);
                if (any != null) deleteAttendanceVacatione.Add(any);
            }

            if (deleteAttendanceVacatione != null && deleteAttendanceVacatione.Any())
                perfoPperAttendanceVacationeRepository.RemoveRange(deleteAttendanceVacatione.ToArray());
            if (addAttendanceVacatione != null && addAttendanceVacatione.Any())
                perfoPperAttendanceVacationeRepository.AddRange(addAttendanceVacatione.ToArray());

            return new ApiResponse(ResponseType.OK, "");

        }
        #endregion

        public ApiResponse<List<AttendanceStatistics>> GetAttendanceStatistics(int allotId)
        {
            var allot = perforPerallotRepository.GetEntity(w => w.ID == allotId);
            if (allot == null)
                throw new PerformanceException("当前绩效记录不存在");

            var types = perfoPperAttendanceTypeRepository.GetEntities(t => t.AllotId == allotId) ?? new List<per_attendance_type>();
            var vacationeData = perfoPperAttendanceVacationeRepository.GetEntities(t => t.AllotId == allotId) ?? new List<per_attendance_vacation>();
            // 只关注请假的人
            var numbers = vacationeData.Select(w => w.PersonnelNumber).ToList();
            var attendanceData = perforPerallotRepository.GetAttendance(allotId)
                .Where(w => numbers.Contains(w.PersonnelNumber))
                .ToList();
            //var attendanceData = perforPerallotRepository.GetAttendance(allotId);

            List<AttendanceStatistics> statistics = new List<AttendanceStatistics>();
            // 交叉补全科室结束时间
            foreach (var personnelNumber in attendanceData.Select(w => w.PersonnelNumber).Distinct())
            {
                var attendances = attendanceData.Where(w => w.PersonnelNumber == personnelNumber).OrderBy(w => w.AttendanceDate);
                for (int i = 0; i < attendances.Count() - 1; i++)
                {
                    var begDate = attendances.ElementAt(i).AttendanceDate.Value.Date;
                    var endDate = attendances.ElementAt(i + 1).AttendanceDate.Value.Date;
                    // 调入科室需要额外减去1天作为上一个科室结束时间
                    var days = attendances.ElementAt(i + 1).Source == Attendance.Type.调入.ToString() ? -1 : 0;
                    if (endDate > begDate)
                    {
                        var stat = new AttendanceStatistics
                        {
                            AllotID = attendances.ElementAt(i).ALLOTID,
                            UnitType = attendances.ElementAt(i).UnitType,
                            AccountingUnit = attendances.ElementAt(i).AccountingUnit,
                            Department = attendances.ElementAt(i).Department,
                            PersonnelNumber = attendances.ElementAt(i).PersonnelNumber,
                            PersonnelName = attendances.ElementAt(i).PersonnelName,
                            BeginDate = begDate,
                            EndDate = endDate.AddDays(days),
                            Detial = new List<AttendanceStatisticsDetial>()
                        };
                        statistics.Add(stat);
                    }
                }
            }

            var vacationes = vacationeData
                .Where(w => w.BegDate.HasValue && w.EndDate.HasValue)
                .Select(w => new
                {
                    w.PersonnelNumber,
                    Type = types.FirstOrDefault(p => p.Id == w.TypeId)?.AttendanceName ?? "考勤类型缺失",
                    Dates = SplitEveryDay(w.BegDate.Value.Date, w.EndDate.Value.Date),
                    Remark = types.FirstOrDefault(p => p.Id == w.TypeId)?.IsDeduction == (int)Attendance.Deduction.核减 ? "核减" : "不核减",
                });


            foreach (var stat in statistics)
            {
                stat.Detial = vacationes
                    .Where(w => w.PersonnelNumber == stat.PersonnelNumber)
                    .Select(w => new AttendanceStatisticsDetial
                    {
                        Title = w.Type,
                        Value = w.Dates.Where(date => date >= stat.BeginDate && date <= stat.EndDate).Count(),
                        Remark = w.Remark,
                    })
                    .ToList();

                int vacationesDays = 0;
                foreach (var item in stat.Detial)
                {
                    if (!item.Remark.Contains("不核减"))
                        vacationesDays += item.Value;
                }
                stat.AttendanceDays = SplitEveryDay(stat.BeginDate, stat.EndDate).Where(date => date >= stat.BeginDate && date <= stat.EndDate).Count() - vacationesDays;
            }
            return new ApiResponse<List<AttendanceStatistics>>(ResponseType.OK, "", statistics);
        }

        // 拆分请假时间段为每个日期
        private List<DateTime> SplitEveryDay(DateTime begin, DateTime end)
        {
            List<DateTime> dates = new List<DateTime>();
            for (int i = 0; i <= (end - begin).TotalDays; i++)
            {
                dates.Add(begin.AddDays(i));
            }
            return dates;
        }


        private List<Dictionary<string, string>> CreateDataRow(SaveCollectData request, Dictionary<string, string> config)
        {
            List<Dictionary<string, string>> allData = new List<Dictionary<string, string>>();

            for (int r = 0; r < request.Data.Length; r++)
            {
                // 创建固定数据列
                Dictionary<string, string> baseData = CreateBaseData(request, config, r);
                allData.Add(baseData);

            }
            return allData;
        }

        private Dictionary<string, string> CreateBaseData(SaveCollectData request, Dictionary<string, string> config, int rownumber)
        {
            Dictionary<string, string> result = new Dictionary<string, string>();
            for (int c = 0; c < request.ColHeaders.Length; c++)
            {
                var header = request.ColHeaders[c];
                var first = config.FirstOrDefault(w => w.Value == header);
                if (!default(KeyValuePair<string, string>).Equals(first)
                    && !result.ContainsKey(header)
                    && request.Data[rownumber].Length > c)
                {
                    result.Add(first.Key, request.Data[rownumber][c]);
                }
            }

            return result;
        }


        public static List<(string, string, Func<per_attendance, object>)> Person { get; } = new List<(string, string, Func<per_attendance, object>)>
        {
            (nameof(per_attendance.PersonnelName), "人员姓名", t => t.PersonnelName),
            (nameof(per_attendance.PersonnelNumber), "员工工号", t => t.PersonnelNumber),
            (nameof(per_attendance.CallInAccountingUnit), "调入核算单元" ,t => t.CallInAccountingUnit),
            (nameof(per_attendance.CallInUnitType), "调入组别", t => t.CallInUnitType),
            (nameof(per_attendance.CallInDate), "调入时间", t => t.CallInDate),
        };

        public static List<(string, string, Func<RecordAttendcance, object>)> Vacation { get; } = new List<(string, string, Func<RecordAttendcance, object>)>
        {
            (nameof(RecordAttendcance.PersonnelName), "人员姓名", t => t.PersonnelName),
            (nameof(RecordAttendcance.PersonnelNumber), "员工工号", t => t.PersonnelNumber),
            (nameof(RecordAttendcance.AttendanceName), "考勤类型" ,t => t.AttendanceName),
            (nameof(RecordAttendcance.BegDate), "开始时间", t => t.BegDate),
            (nameof(RecordAttendcance.EndDate), "结束时间", t => t.EndDate),
        };
    }
}
