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

namespace Performance.Services.AllotCompute
{
    /// <summary>
    /// 最终绩效计算
    /// </summary>
    public class ResultComputeService : IAutoInjection
    {
        private readonly BaiscNormService baiscNormService;
        private readonly ComputeDirector computeDirector;
        private readonly BudgetService budgetService;
        private readonly PerforPeremployeeRepository perforPeremployeeRepository;
        private readonly PerforPerallotRepository perforPerallotRepository;
        //private readonly PerforAgcomputeRepository perforAgcomputeRepository;
        private readonly PerforAgsecondallotRepository perforAgsecondallotRepository;
        private readonly IMapper _mapper;
        private readonly PerforHospitalRepository hospitalRepository;
        private readonly PerforImemployeeRepository perforImEmployeeRepository;
        private readonly PerforRescomputeRepository perforRescomputeRepository;
        private readonly PerforResbaiscnormRepository perforResbaiscnormRepository;
        private readonly PerforResspecialunitRepository perforResspecialunitRepository;
        private readonly PerforImaccountbasicRepository perforImaccountbasicRepository;
        private readonly PerforResaccountRepository perforResaccountRepository;
        private readonly LogManageService logManageService;
        private readonly PerforImemployeeclinicRepository perforImemployeeclinicRepository;
        private readonly PerforImemployeelogisticsRepository perforImemployeelogisticsRepository;
        private readonly ILogger logger;

        public ResultComputeService(
            IMapper mapper,
            PerforHospitalRepository hospitalRepository,
            PerforImemployeeRepository perforImEmployeeRepository,
            PerforRescomputeRepository perforRescomputeRepository,
            PerforResbaiscnormRepository perforResbaiscnormRepository,
            PerforResspecialunitRepository perforResspecialunitRepository,
            PerforImaccountbasicRepository perforImaccountbasicRepository,
            PerforResaccountRepository perforResaccountRepository,
            BaiscNormService baiscNormService, ComputeDirector computeDirector,
            LogManageService logManageService, BudgetService budgetService,
            PerforPeremployeeRepository perforPeremployeeRepository,
            PerforPerallotRepository perforPerallotRepository,
            //PerforAgcomputeRepository perforAgcomputeRepository,
            PerforAgsecondallotRepository perforAgsecondallotRepository,
            PerforImemployeeclinicRepository perforImemployeeclinicRepository,
            PerforImemployeelogisticsRepository perforImemployeelogisticsRepository,
            ILogger<ResultComputeService> logger)
        {
            this.baiscNormService = baiscNormService;
            this.computeDirector = computeDirector;
            _mapper = mapper;
            this.hospitalRepository = hospitalRepository;
            this.perforImEmployeeRepository = perforImEmployeeRepository;
            this.perforRescomputeRepository = perforRescomputeRepository;
            this.perforResbaiscnormRepository = perforResbaiscnormRepository;
            this.perforResspecialunitRepository = perforResspecialunitRepository;
            this.perforImaccountbasicRepository = perforImaccountbasicRepository;
            this.perforResaccountRepository = perforResaccountRepository;
            this.logManageService = logManageService;
            this.budgetService = budgetService;
            this.perforPeremployeeRepository = perforPeremployeeRepository;
            this.perforPerallotRepository = perforPerallotRepository;
            //this.perforAgcomputeRepository = perforAgcomputeRepository;
            this.perforAgsecondallotRepository = perforAgsecondallotRepository;
            this.perforImemployeeclinicRepository = perforImemployeeclinicRepository;
            this.perforImemployeelogisticsRepository = perforImemployeelogisticsRepository;
            this.logger = logger;
        }

        /// <summary>
        /// 计算最终数据
        /// </summary>
        /// <param name="excel"></param>
        public List<res_baiscnorm> Compute(per_allot allot, List<PerSheet> accountSheet)
        {
            //取出人员信息
            var empolyeeList = perforImemployeeclinicRepository.GetEntities(t => t.AllotID == allot.ID);
            var accountbasicList = perforImaccountbasicRepository.GetEntities(t => t.AllotID == allot.ID);

            List<ComputeEmployee> computeEmployees = _mapper.Map<List<ComputeEmployee>>(empolyeeList);

            logManageService.WriteMsg("正在生成绩效", "科室主任、护士长 最终绩效数据计算", 1, allot.ID, "ReceiveMessage");
            var computResult = computeDirector.Compute(computeEmployees, accountSheet, allot);
            //计算 绩效标准 基数（科主任、副主任、护士长 =>> 平均值）
            List<res_baiscnorm> baiscnormList = new List<res_baiscnorm>();
            baiscNormService.ComputeAvg(baiscnormList, computeEmployees, computResult);
            baiscNormService.DocterNurseBaiscnorm(baiscnormList, accountbasicList, accountSheet);

            var empolyeeList2 = perforImEmployeeRepository.GetEntities(t => t.AllotID == allot.ID);
            var computeEmployees2 = _mapper.Map<List<ComputeEmployee>>(empolyeeList2);
            logManageService.WriteMsg("正在生成绩效", "行政中高层 最终绩效数据计算", 1, allot.ID, "ReceiveMessage");
            var computResult2 = computeDirector.Compute(computeEmployees2, allot, baiscnormList, accountbasicList);

            var empolyeeList3 = perforImemployeelogisticsRepository.GetEntities(t => t.AllotID == allot.ID);
            var computeEmployees3 = _mapper.Map<List<ComputeEmployee>>(empolyeeList3);
            logManageService.WriteMsg("正在生成绩效", "行政后勤 最终绩效数据计算", 1, allot.ID, "ReceiveMessage");
            var computResult3 = computeDirector.Compute(computeEmployees3, allot, baiscnormList, accountbasicList);

            //计算 行政中高层 平均值
            baiscNormService.ComputeOtherAvg(baiscnormList, computResult2, empolyeeList2);
            //计算 行政人员 平均值
            baiscNormService.ComputeOtherAvg(baiscnormList, computResult3, empolyeeList3);

            var computes = _mapper.Map<List<res_compute>>(computResult);
            computes.AddRange(_mapper.Map<List<res_compute>>(computResult2));
            computes.AddRange(_mapper.Map<List<res_compute>>(computResult3));
            computes.ForEach(t => t.AllotID = allot.ID);
            perforRescomputeRepository.AddRange(computes.ToArray());

            baiscnormList.ForEach(t => t.AllotID = allot.ID);
            logManageService.WriteMsg("正在生成绩效", "保存最终绩效数据", 1, allot.ID, "ReceiveMessage");

            return baiscnormList;
        }

        /// <summary>
        /// 特殊科室绩效计算
        /// </summary>
        /// <param name="excel"></param>
        /// <param name="allot"></param>
        public void SpecialUnitCompute(PerExcel excel, per_allot allot, List<res_baiscnorm> baiscnormList)
        {
            var isBudget = budgetService.GetAdjustAndGrant(allot, out decimal adjust, out decimal grant);
            var typeList = EnumHelper.GetItems<PerforType>();

            var specialUnit = excel.PerSheet.FirstOrDefault(t => t.SheetType == SheetType.SpecialUnit);
            if (specialUnit == null || specialUnit.PerData.Count == 0)
                return;

            var dataList = CalculateSpecialUnit(specialUnit, allot, baiscnormList, typeList);

            //取出科室
            var accountList = excel.PerSheet.FirstOrDefault(t => t.SheetType == SheetType.AccountBasic)?.PerData?.Select(t => (PerDataAccountBaisc)t);
            var adjustLaterOtherFee = excel.PerSheet.FirstOrDefault(t => t.SheetType == SheetType.AccountAdjustLaterOtherFee)?.PerData?.Select(t => (PerData)t);

            List<res_specialunit> resDataList = new List<res_specialunit>();

            var groupSpeList = dataList.GroupBy(t => t.AccountingUnit).Select(t => new { AccountingUnit = t.Key, Number = t.OrderBy(w => w.RowNumber).FirstOrDefault().Number, });

            var empolyeeList = perforImemployeeclinicRepository.GetEntities(t => t.AllotID == allot.ID && t.UnitType == UnitType.特殊核算组.ToString());
            List<ComputeEmployee> computeEmployees = _mapper.Map<List<ComputeEmployee>>(empolyeeList);
            List<ComputeResult> computeList = new List<ComputeResult>();

            foreach (var group in groupSpeList)
            {
                // 获取科室测算信息
                var dept = accountList?.FirstOrDefault(t => t.UnitType == UnitType.特殊核算组.ToString() && t.AccountingUnit == group.AccountingUnit);
                //获取需要聚合的科室
                var accountDataList = dataList.Where(t => t.AccountingUnit == group.AccountingUnit);
                //计算量化指标子项合计
                var sumValue = accountDataList.Sum(t =>
                {
                    // 新都医院在特殊科室计算时，如果取核算基数计算时带入人数计算
                    decimal? headcount = null;
                    if (typeList.Any(o => o.Description == t.QuantitativeIndicators))
                        headcount = group.Number;
                    if (!string.IsNullOrEmpty(t.QuantitativeIndicators) && t.QuantitativeIndicators.LastIndexOf("人均绩效") > -1)
                        headcount = group.Number;
                    if (!headcount.HasValue || headcount == 0)
                        headcount = 1;
                    return t.Quantity * t.QuantitativeIndicatorsValue * headcount;
                });

                foreach (var item in accountDataList)
                {
                    //科室奖罚汇总结果
                    //var extra = accountExtras?.FirstOrDefault(w => w.UnitType == UnitType.特殊核算组.ToString() && w.AccountingUnit == dept?.AccountingUnit)?.TotelValue;
                    //var drugExtra = drugExtras?.FirstOrDefault(w => w.UnitType == UnitType.特殊核算组.ToString() && w.AccountingUnit == dept?.AccountingUnit)?.TotelValue;
                    //var materialsExtra = materialsExtras?.FirstOrDefault(w => w.UnitType == UnitType.特殊核算组.ToString() && w.AccountingUnit == dept?.AccountingUnit)?.TotelValue;
                    //var scoreAverage = accountScoreAverages?.FirstOrDefault(w => w.UnitType == UnitType.特殊核算组.ToString() && w.AccountingUnit == dept?.AccountingUnit)?.TotelValue;

                    // 夜班绩效 从医院奖罚的明细项中获取
                    var nightShift = adjustLaterOtherFee?.FirstOrDefault(w => w.UnitType == dept?.UnitType && w.AccountingUnit == dept?.AccountingUnit && w.TypeName?.Trim() == "夜班绩效")?.CellValue ?? 0;

                    decimal? headcount = null;
                    if (typeList.Any(o => o.Description == item.QuantitativeIndicators))
                        headcount = group.Number;
                    if (!string.IsNullOrEmpty(item.QuantitativeIndicators) && item.QuantitativeIndicators.LastIndexOf("人均绩效") > -1)
                        headcount = group.Number;
                    if (!headcount.HasValue || headcount == 0)
                        headcount = 1;
                    //var xxx = item.Quantity * item.QuantitativeIndicatorsValue * headcount;

                    var res = new res_specialunit
                    {
                        AllotID = allot.ID,
                        AccountingUnit = group.AccountingUnit,
                        Department = group.AccountingUnit,
                        // 优先使用4.1中人数
                        Number = dept?.Number ?? group.Number,
                        QuantitativeIndicators = item.QuantitativeIndicators,
                        Quantity = item.Quantity,
                        QuantitativeIndicatorsValue = item.QuantitativeIndicatorsValue,
                        QuantitativeFee = item.Quantity * item.QuantitativeIndicatorsValue * headcount,
                        //ScoringAverage = scoreAverage.HasValue ? scoreAverage : dept?.ScoringAverage,
                        ScoringAverage = dept?.ScoringAverage ?? 1,
                        //OtherPerfor = dept?.OtherPerfor1,
                        //Punishment = (extra ?? 0),
                        //MedicineExtra = (drugExtra ?? 0),
                        //MaterialsExtra = (materialsExtra ?? 0),
                        Punishment = dept?.Extra ?? 0,
                        MedicineExtra = dept?.MedicineExtra ?? 0,
                        MaterialsExtra = dept?.MaterialsExtra ?? 0,

                        Adjust = (isBudget ? adjust : dept?.AdjustFactor) ?? 1,

                        AssessBeforeOtherFee = dept?.AssessBeforeOtherFee ?? 0,
                        AssessLaterOtherFee = dept?.AssessLaterOtherFee ?? 0,
                        AdjustLaterOtherFee = dept?.AdjustLaterOtherFee ?? 0,
                        NightShiftWorkPerforFee = nightShift,
                    };
                    logger.LogInformation($"特殊核算组-{group.AccountingUnit},sumValue:{sumValue},预算比例:{dept?.BasicFactor ?? -100}");
                    res.ResultsTotalFee = Math.Round((sumValue * (dept?.BasicFactor ?? 1m)) ?? 0, MidpointRounding.AwayFromZero);
                    res.PerforTotal = res.ResultsTotalFee + res.AssessBeforeOtherFee;
                    res.GiveFee = Math.Round((res.PerforTotal * res.ScoringAverage + res.MedicineExtra + res.MaterialsExtra + res.Punishment + res.AssessLaterOtherFee) ?? 0, MidpointRounding.AwayFromZero);
                    res.RealGiveFee = Math.Round(res.GiveFee * res.Adjust + res.AdjustLaterOtherFee ?? 0, MidpointRounding.AwayFromZero);
                    res.Avg = Math.Round((res.Number != 0 ? res.PerforTotal / res.Number : null) ?? 0, MidpointRounding.AwayFromZero);


                    resDataList.Add(res);
                }

                if (computeEmployees == null || !computeEmployees.Any()) continue;

                var empolyees = computeEmployees.Where(t => t.AccountingUnit == group.AccountingUnit);
                if (empolyees == null || !empolyees.Any()) continue;

                foreach (var empolyee in empolyees)
                {
                    var resAccount = resDataList.FirstOrDefault(t => t.AccountingUnit == empolyee.AccountingUnit);
                    if (resAccount == null)
                        continue;

                    // 优先取 实际人均绩效
                    var avg = (empolyee.FitPeopleValue.HasValue)
                        ? empolyee.FitPeopleValue
                        : resAccount.Number == 0 ? 0 : resAccount.PerforTotal / resAccount.Number;
                    var effAvg = empolyee.PermanentStaff == 0 ? 0 : resAccount.PerforTotal / empolyee.PermanentStaff;

                    var empolyeeAdjust = isBudget ? adjust : empolyee.Adjust;
                    var compute = new ComputeResult
                    {
                        UnitType = UnitType.特殊核算组.ToString(),
                        AccountingUnit = group.AccountingUnit,

                        AccountType = AccountTypeUnit.Recognition(empolyee.JobTitle, AccountUnitType.科主任),
                        EmployeeName = empolyee.DoctorName,
                        FitPeople = empolyee.FitPeople,
                        JobTitle = empolyee.JobTitle,
                        JobNumber = empolyee.JobNumber,
                        ScoreAverageRate = empolyee.ScoreAverageRate,
                        Punishment = empolyee.Punishment ?? 0,
                        //OtherPerfor = empolyee.OtherPerfor,
                        OtherManagePerfor = empolyee?.OtherManagePerfor ?? 0,
                        Number = resAccount.Number,
                        PermanentStaff = empolyee.PermanentStaff,
                        PerforTotal = resAccount.PerforTotal,
                        Adjust = empolyeeAdjust ?? 1m,
                        Grant = isBudget ? grant : empolyee.Management,
                        Attendance = empolyee.Attendance ?? 0,
                        AssessBeforeOtherFee = empolyee?.AssessBeforeOtherFee ?? 0,
                        AssessLaterOtherFee = empolyee?.AssessLaterOtherFee ?? 0,
                        AdjustLaterOtherFee = empolyee?.AdjustLaterOtherFee ?? 0,
                        Efficiency = effAvg * (empolyee.Efficiency ?? 0),
                        Scale = resAccount.PerforTotal * (empolyee.Scale ?? 0),
                    };

                    compute.Avg = avg * (empolyee.Basics ?? 0) * compute.Attendance;
                    // 考核前管理绩效
                    compute.ShouldGiveFee = Math.Round((compute.Efficiency + compute.Scale) * compute.Grant + compute.OtherManagePerfor ?? 0, MidpointRounding.AwayFromZero);
                    // 考核后管理绩效
                    compute.AssessLaterManagementFee = Math.Round(compute.ShouldGiveFee * compute.ScoreAverageRate * compute.Attendance + compute.Punishment ?? 0, MidpointRounding.AwayFromZero);
                    // 考核前绩效
                    compute.PerforSumFee = compute.Attendance == 0 ? Math.Round(compute.ShouldGiveFee ?? 0, MidpointRounding.AwayFromZero) : Math.Round(compute.Avg / compute.Attendance + compute.ShouldGiveFee ?? 0, MidpointRounding.AwayFromZero);
                    // 考核后绩效
                    compute.GiveFee = Math.Round(compute.Avg + compute.AssessLaterManagementFee ?? 0, MidpointRounding.AwayFromZero);
                    // 参考基数专用绩效合计
                    compute.BaiscNormPerforTotal = compute.PerforSumFee;
                    // 实发绩效
                    compute.RealGiveFee = Math.Round((compute.Avg + compute.AssessLaterManagementFee) * compute.Adjust + compute.AdjustLaterOtherFee ?? 0, MidpointRounding.AwayFromZero);

                    //compute.Efficiency = compute.Avg * (empolyee.Efficiency ?? 1);
                    //compute.Scale = compute.PerforTotal * (empolyee.Scale ?? 1);
                    ////应发管理绩效
                    //compute.ShouldGiveFee = Math.Round((compute.Efficiency + compute.Scale) * compute.Grant ?? 0);
                    ////绩效合计
                    //compute.PerforSumFee = Math.Round(compute.Avg + compute.ShouldGiveFee + compute.AssessBeforeOtherFee ?? 0);
                    ////应发绩效
                    ////compute.GiveFee = compute.PerforSumFee;
                    //compute.GiveFee = Math.Round(compute.PerforSumFee * compute.ScoreAverageRate * compute.Attendance + compute.Punishment + compute.AssessLaterOtherFee ?? 0);
                    ////实发绩效
                    ////compute.RealGiveFee = (compute.GiveFee * compute.ScoreAverageRate + (compute.Punishment ?? 0) + (compute.OtherPerfor ?? 0)) * (compute.Adjust ?? 1m);
                    //compute.RealGiveFee = Math.Round(compute.GiveFee * compute.Adjust + compute.AdjustLaterOtherFee ?? 0);
                    //// 参考基数专用绩效合计
                    //compute.BaiscNormPerforTotal = compute.PerforSumFee;

                    computeList.Add(compute);
                }
            }
            var computes = _mapper.Map<List<res_compute>>(computeList);
            computes.ForEach(t => t.AllotID = allot.ID);
            perforRescomputeRepository.AddRange(computes.ToArray());
            perforResspecialunitRepository.AddRange(resDataList.ToArray());
        }

        private IEnumerable<PerDataSpecialUnit> CalculateSpecialUnit(PerSheet specialUnit, per_allot allot, List<res_baiscnorm> baiscnormList, List<EnumItem> typeList)
        {
            var dataList = specialUnit.PerData.Select(t => (PerDataSpecialUnit)t);
            var specialEmployee = perforImemployeeclinicRepository.GetEntities(t => t.AllotID == allot.ID);

            //替换考核基数
            foreach (var item in dataList)
            {
                if (specialEmployee != null && specialEmployee.FirstOrDefault(t => t.AccountingUnit == item.AccountingUnit) != null)
                {
                    item.Efficiency = specialEmployee.FirstOrDefault(t => t.AccountingUnit == item.AccountingUnit).Efficiency ?? 1;
                    item.Scale = specialEmployee.FirstOrDefault(t => t.AccountingUnit == item.AccountingUnit).Scale ?? 1;
                    item.Management = specialEmployee.FirstOrDefault(t => t.AccountingUnit == item.AccountingUnit).Management ?? 1;
                }
                var type = typeList.FirstOrDefault(o => o.Description == item.QuantitativeIndicators);
                if (type != null)
                {
                    if (type.Value == (int)PerforType.医生护士平均)
                    {
                        var doctor = baiscNormService.GetBaiscNorm(baiscnormList, PerforType.临床医生) ?? 0;
                        var nurse = baiscNormService.GetBaiscNorm(baiscnormList, PerforType.护士) ?? 0;
                        // 添加参数计算
                        item.Quantity = item.Quantity ?? (doctor + nurse) / 2;
                    }
                    else
                    {
                        //var radio = perforImEmployeeRepository.GetEntities(p => p.FitPeople == EnumHelper.GetDescription((PerforType)type.Value) && p.AllotID == allot.ID)
                        //    ?.FirstOrDefault().FitPeopleRatio ?? 1;
                        var basic = baiscNormService.GetBaiscNorm(baiscnormList, (PerforType)type.Value);
                        // 添加参数计算
                        item.Quantity = item.Quantity ?? (basic ?? 0);
                    }
                }
            }
            return dataList;
        }

        #region 预留金额

        ///// <summary>
        ///// 二次绩效审核通过后修改绩效预留金额
        ///// </summary>
        ///// <param name="secondId"></param>
        //public void SaveSecondReserved(int secondId)
        //{
        //    var second = perforAgsecondallotRepository.GetEntity(t => t.Id == secondId);
        //    if (second == null)
        //        throw new PerformanceException("参数信息无效");

        //    var allot = perforPerallotRepository.GetEntity(t => t.ID == second.AllotId);
        //    if (allot == null)
        //        throw new PerformanceException("参数信息无效");

        //    var again = perforAgcomputeRepository.GetEntities(t => t.AllotId == allot.ID);
        //    if (again != null && again.Any())
        //    {
        //        var empDic = perforPeremployeeRepository.GetEntities(w => w.AllotId == allot.ID);

        //        var group = again.GroupBy(t => new { t.Department, t.JobNumber, t.PersonName })
        //            .Select(t => new ComputeResponse
        //            {
        //                UnitType = second.UnitType,
        //                AccountingUnit = t.Key.Department,
        //                JobNumber = t.Key.JobNumber,
        //                EmployeeName = t.Key.PersonName,
        //                RealGiveFee = t.Sum(g => g.RealGiveFee)
        //            });

        //        AddOrUpdate(allot, empDic, group);
        //    }
        //}

        ///// <summary>
        ///// 绩效生成完成后修改绩效预留金额
        ///// </summary>
        ///// <param name="allot"></param>
        //public void SaveReserved(per_allot allot, int hospitalId)
        //{
        //    var mTypes = new List<string> { AccountUnitType.行政中层.ToString(), AccountUnitType.行政高层.ToString(), AccountUnitType.行政工勤.ToString() };

        //    var hospital = hospitalRepository.GetEntity(w => w.ID == hospitalId);
        //    if (hospital?.IsShowManage == 1)
        //        mTypes.AddRange(new List<string> { AccountUnitType.护士长.ToString(), AccountUnitType.科主任.ToString() });

        //    var resComputes = perforRescomputeRepository
        //        .GetEntities(t => t.AllotID == allot.ID && mTypes.Contains(t.AccountType) && (string.IsNullOrEmpty(t.NeedSecondAllot) || t.NeedSecondAllot == "否"))
        //        ?.OrderByDescending(t => t.AccountingUnit);

        //    if (resComputes != null && resComputes.Any())
        //    {
        //        var empDic = perforPeremployeeRepository.GetEntities(w => w.AllotId == allot.ID);

        //        var group = resComputes.GroupBy(t => new { t.UnitType, t.AccountingUnit, t.EmployeeName, t.JobNumber })
        //              .Select(t => new ComputeResponse
        //              {
        //                  UnitType = t.Key.UnitType,
        //                  AccountingUnit = t.Key.AccountingUnit,
        //                  EmployeeName = t.Key.EmployeeName,
        //                  JobNumber = t.Key.JobNumber,
        //                  RealGiveFee = t.Sum(g => g.RealGiveFee)
        //              });
        //        AddOrUpdate(allot, empDic, group);
        //    }
        //}

        //private void AddOrUpdate(per_allot allot, List<per_employee> empDic, IEnumerable<ComputeResponse> group)
        //{
        //    var reserveds = perforresreservedRepository.GetEntities(w => w.HospitalId == allot.HospitalId && w.Year == allot.Year);
        //    List<res_reserved> updates = new List<res_reserved>(), inserts = new List<res_reserved>();
        //    foreach (var item in group)
        //    {
        //        var ratio = empDic?.FirstOrDefault(w => w.PersonnelNumber == item.JobNumber)?.ReservedRatio ?? 0;
        //        var reserved = reserveds?.FirstOrDefault(w => w.AccountingUnit == item.AccountingUnit && w.JobNumber == item.JobNumber);
        //        if (reserved == null)
        //        {
        //            reserved = new res_reserved
        //            {
        //                UnitType = item.UnitType,
        //                HospitalId = allot.HospitalId,
        //                Year = allot.Year,
        //                AccountingUnit = item.AccountingUnit,
        //                JobNumber = item.JobNumber,
        //                EmployeeName = item.EmployeeName,
        //            };
        //            inserts.Add(reserved);
        //        }
        //        else
        //            updates.Add(reserved);

        //        ChangeRealGiveFee(reserved, allot, item.RealGiveFee ?? 0, ratio);
        //    }
        //    perforresreservedRepository.AddRange(inserts.ToArray());
        //    perforresreservedRepository.UpdateRange(updates.ToArray());
        //}

        ///// <summary>
        ///// 修改绩效金额
        ///// </summary>
        ///// <param name="reserved"></param>
        ///// <param name="allot"></param>
        ///// <param name="realGiveFee"></param>
        ///// <param name="ratio"></param>
        //private void ChangeRealGiveFee(res_reserved reserved, per_allot allot, decimal realGiveFee, decimal ratio)
        //{
        //    if (allot.Month == 1)
        //    {
        //        reserved.JanFee = realGiveFee;
        //        reserved.JanRatio = ratio;
        //    }
        //    else if (allot.Month == 2)
        //    {
        //        reserved.FebFee = realGiveFee;
        //        reserved.FebRatio = ratio;
        //    }
        //    else if (allot.Month == 3)
        //    {
        //        reserved.MarFee = realGiveFee;
        //        reserved.MarRatio = ratio;
        //    }
        //    else if (allot.Month == 4)
        //    {
        //        reserved.AprFee = realGiveFee;
        //        reserved.AprRatio = ratio;
        //    }
        //    else if (allot.Month == 5)
        //    {
        //        reserved.MayFee = realGiveFee;
        //        reserved.MayRatio = ratio;
        //    }
        //    else if (allot.Month == 6)
        //    {
        //        reserved.JunFee = realGiveFee;
        //        reserved.JunRatio = ratio;
        //    }
        //    else if (allot.Month == 7)
        //    {
        //        reserved.JulFee = realGiveFee;
        //        reserved.JulRatio = ratio;
        //    }
        //    else if (allot.Month == 8)
        //    {
        //        reserved.AugFee = realGiveFee;
        //        reserved.AugRatio = ratio;
        //    }
        //    else if (allot.Month == 9)
        //    {
        //        reserved.SepFee = realGiveFee;
        //        reserved.SepRatio = ratio;
        //    }
        //    else if (allot.Month == 10)
        //    {
        //        reserved.OctFee = realGiveFee;
        //        reserved.OctRatio = ratio;
        //    }
        //    else if (allot.Month == 11)
        //    {
        //        reserved.NovFee = realGiveFee;
        //        reserved.NovRatio = ratio;
        //    }
        //    else if (allot.Month == 12)
        //    {
        //        reserved.DecFee = realGiveFee;
        //        reserved.DecRatio = ratio;
        //    }
        //}

        #endregion 预留金额

        /// <summary>
        /// 创建科室二次分配
        /// </summary>
        /// <param name="allot"></param>
        public void GenerateSecondAllot(per_allot allot)
        {
            List<ag_secondallot> tempSecond = new List<ag_secondallot>();
            List<ag_secondallot> insSecond = new List<ag_secondallot>();
            List<ag_secondallot> updSecond = new List<ag_secondallot>();
            List<ag_secondallot> delSecond = new List<ag_secondallot>();

            var types = new List<int> { (int)UnitType.行政高层, (int)UnitType.行政中层, (int)UnitType.行政后勤 };
            //// 获取医院是否开启后勤二次分配
            //var hospital = hospitalRepository.GetEntity(w => w.ID == allot.HospitalId);
            //if (hospital?.IsOpenLogisticsSecondAllot != 1)
            //    types.Add((int)UnitType.行政后勤);

            var accountUnit = perforResaccountRepository.GetEntities(t => t.AllotID == allot.ID && !types.Contains(t.UnitType.Value));
            // 查询需要进行二次分配的行政后勤科室
            var xzAccountUnit = perforResaccountRepository.GetEntities(t => t.AllotID == allot.ID && t.UnitType.Value == (int)UnitType.行政后勤 && t.NeedSecondAllot == "是");
            if (xzAccountUnit != null && xzAccountUnit.Count > 0)
                (accountUnit ?? new List<res_account>()).AddRange(xzAccountUnit);

            var specialList = perforResspecialunitRepository.GetEntities(t => t.AllotID == allot.ID);

            if (accountUnit != null)
            {
                foreach (var item in accountUnit)
                {
                    if (!tempSecond.Any(f => f.UnitType == ((UnitType)item.UnitType).ToString() && f.Department == item.AccountingUnit))
                    {
                        tempSecond.Add(new ag_secondallot
                        {
                            AllotId = allot.ID,
                            Year = allot.Year,
                            Month = allot.Month,
                            UnitType = ((UnitType)item.UnitType).ToString(),
                            Department = item.AccountingUnit,
                            NightShiftWorkPerforFee = item.NightShiftWorkPerforFee,
                            PreRealGiveFee = item.RealGiveFee,
                        });
                    }
                }
            }
            if (specialList != null)
            {
                foreach (var item in specialList.Select(w => new { w.AccountingUnit, w.NightShiftWorkPerforFee, w.RealGiveFee }).Distinct())
                {
                    if (!tempSecond.Any(f => f.UnitType == UnitType.特殊核算组.ToString() && f.Department == item.AccountingUnit))
                    {
                        tempSecond.Add(new ag_secondallot
                        {
                            AllotId = allot.ID,
                            Year = allot.Year,
                            Month = allot.Month,
                            UnitType = UnitType.特殊核算组.ToString(),
                            Department = item.AccountingUnit,
                            NightShiftWorkPerforFee = item.NightShiftWorkPerforFee,
                            PreRealGiveFee = item.RealGiveFee,
                        });
                    }
                }
            }

            var secondList = perforAgsecondallotRepository.GetEntities(t => t.AllotId == allot.ID && t.Year == allot.Year && t.Month == allot.Month);

            foreach (var item in tempSecond)
            {
                var second = secondList?.FirstOrDefault(f => f.UnitType == item.UnitType && f.Department == item.Department);
                if (second == null)
                {
                    insSecond.Add(new ag_secondallot
                    {
                        AllotId = allot.ID,
                        Year = allot.Year,
                        Month = allot.Month,
                        UnitType = item.UnitType,
                        Department = item.Department,
                        PreRealGiveFee = item.PreRealGiveFee,
                        NightShiftWorkPerforFee = item.NightShiftWorkPerforFee,
                        Status = 1,
                        NursingDeptStatus = 1,
                    });
                }
                else
                {
                    /*
                    var backResult = Math.Abs((second.PreRealGiveFee ?? 0) - (item.RealGiveFee ?? 0)) >= 0.5m
                        || Math.Abs((second.NightShiftWorkPerforFee ?? 0) - (item.NightShiftWorkPerforFee ?? 0)) >= 0.5m;
                    if (backResult && second.Status > 1)
                    {
                        second.Status = 4;
                        second.Remark = "科室绩效结果发生变更，需要重新提交";
                        second.NursingDeptStatus = 4;
                        second.NursingDeptRemark = "科室绩效结果发生变更，需要重新提交";
                    }
                    */
                    second.PreRealGiveFee = item.PreRealGiveFee;
                    second.NightShiftWorkPerforFee = item.NightShiftWorkPerforFee;
                    updSecond.Add(second);
                }
            }

            if (secondList != null && secondList.Any())
            {
                foreach (var item in secondList)
                {
                    var second = tempSecond?.FirstOrDefault(f => f.UnitType == item.UnitType && f.Department == item.Department);
                    if (second == null)
                    {
                        item.PreRealGiveFee = 0;
                        delSecond.Add(item);
                    }
                }
            }

            if (insSecond.Any())
                perforAgsecondallotRepository.AddRange(insSecond.ToArray());

            if (updSecond.Any())
            {
                perforAgsecondallotRepository.UpdateRange(updSecond.ToArray());
                /*
                foreach (var item in updSecond.Where(w => w.Status == 4))
                {
                    // 自动驳回，需要清空该科室历史数据 
                    perforAgsecondallotRepository.DeleteComputeHistory(item.Id);
                }
                */
            }

            if (delSecond.Any())
                perforAgsecondallotRepository.UpdateRange(delSecond.ToArray());

        }


        public List<IssuedPromptResponse> IssuedPrompt(per_allot allot, AllotRequest request, ref bool isIssued)
        {
            List<ag_secondallot> tempSecond = new List<ag_secondallot>();
            var promptSeconds = new List<IssuedPromptResponse>();


            var secondList = perforAgsecondallotRepository.GetEntities(t => t.AllotId == allot.ID && t.Year == allot.Year && t.Month == allot.Month);
            if (secondList == null || !secondList.Any())
                return new List<IssuedPromptResponse>();

            var IsOpen = hospitalRepository.GetEntity(t => t.ID == allot.HospitalId).IsOpenNursingDeptAudit == 1;
            var status = new[] { 2, 3 };
            foreach (var item in secondList)
            {
                var second = secondList?.FirstOrDefault(f => f.UnitType == item.UnitType && f.Department == item.Department);
                
                var isDiffer = (item.RealGiveFee ?? 0) != (item.PreRealGiveFee ?? 0);

                if ((item.RealGiveFee ?? 0) == 0 && (item.PreRealGiveFee ?? 0) > 0)
                {
                    var promptSecond = _mapper.Map<IssuedPromptResponse>(item);
                    promptSecond.RealGiveFee = item.PreRealGiveFee;
                    promptSecond.StatusRemake = "";
                    promptSecond.IssueStatus = 4;
                    promptSeconds.Add(promptSecond);
                }
                else if (isDiffer && !status.Contains(item.Status.Value) && (IsOpen==true? !status.Contains(item.NursingDeptStatus.Value):true))
                {
                    var promptSecond = _mapper.Map<IssuedPromptResponse>(item);
                    promptSecond.StatusRemake = $@"未提交科室实发绩效变更,原金额:{item.RealGiveFee ?? 0}";
                    promptSecond.IssueStatus = 3;
                    promptSecond.RealGiveFee = item.PreRealGiveFee;
                    promptSeconds.Add(promptSecond);
                }
                else if (isDiffer && status.Contains(item.Status.Value) && (IsOpen==true? status.Contains(item.NursingDeptStatus.Value):true))
                {
                    var promptSecond = _mapper.Map<IssuedPromptResponse>(item);
                    promptSecond.StatusRemake = $@"已提交或已审核科室实发绩效变更驳回,原金额:{item.RealGiveFee ?? 0}";
                    promptSecond.IssueStatus = 2;
                    promptSecond.RealGiveFee = item.PreRealGiveFee;

                    promptSecond.Status = 4;
                    promptSecond.Remark = "科室绩效结果发生变更，需要重新提交";
                    if (IsOpen)
                    {
                        promptSecond.NursingDeptStatus = 4;
                        promptSecond.NursingDeptRemark = "科室绩效结果发生变更，需要重新提交";
                    }

                    promptSeconds.Add(promptSecond);
                }
                else if ((item.RealGiveFee ?? 0) >= 0 && (item.PreRealGiveFee ?? 0) == 0)
                {
                    var promptSecond = _mapper.Map<IssuedPromptResponse>(item);
                    promptSecond.StatusRemake = "";
                    promptSecond.IssueStatus = 1;
                    promptSeconds.Add(promptSecond);
                }
            }


            if (!string.IsNullOrEmpty(request.SearchQuery))
                promptSeconds = promptSeconds?.FindAll(t => t.Department.Contains(request.SearchQuery));
            if (!string.IsNullOrEmpty(request.QueryStatus.ToString()))
                promptSeconds = promptSeconds?.FindAll(t => t.IssueStatus == request.QueryStatus);

            if (request.isIssued == 1)
            {
                if (promptSeconds.Any(t => t.IssueStatus != 1))
                {
                    var updSecondQuery = promptSeconds.Where(t => t.IssueStatus != 1);
                    var updSeconds = secondList.Where(w => updSecondQuery.Select(t => t.Id).Contains(w.Id)) ?? new List<ag_secondallot>();
                    updSeconds.ToList().ForEach(t => t.RealGiveFee = t.PreRealGiveFee);
                    perforAgsecondallotRepository.UpdateRange(updSeconds.ToArray());
                }
                if (promptSeconds.Any(t => t.IssueStatus == 1))
                {
                    //删除
                    var delSecondQuery = promptSeconds.Where(t => t.IssueStatus == 1);
                    var delSecond = secondList.Where(w => delSecondQuery.Select(t => t.Id).Contains(w.Id)) ?? new List<ag_secondallot>();
                    //delSecond.ToList().ForEach(t => t.RealGiveFee = t.PreRealGiveFee);
                    perforAgsecondallotRepository.RemoveRange(delSecond.ToArray());
                }
                isIssued = true;
            }

            return promptSeconds.OrderBy(t => t.IssueStatus).ToList();
        }

    }
}
