using AutoMapper;
using Microsoft.Extensions.Options;
using Performance.DtoModels;
using Performance.DtoModels.AppSettings;
using Performance.EntityModels;
using Performance.Infrastructure;
using Performance.Repository;
using System;
using System.Collections.Generic;
using System.Collections.Immutable;
using System.Linq;
using System.Linq.Expressions;
using System.Text;

namespace Performance.Services
{
    public class SecondAllotService : IAutoInjection
    {
        private readonly Application application;
        private readonly PerforUserRepository perforUserRepository;
        private readonly PerforUserhospitalRepository perforUserhospitalRepository;
        private readonly PerforPerallotRepository perforPerallotRepository;
        private readonly PerforAgsecondallotRepository perforAgsecondallotRepository;
        private readonly PerforResaccountRepository perforResaccountRepository;
        private readonly PerforUserroleRepository userroleRepository;
        private readonly PerforAgworkloadRepository perforAgworkloadRepository;
        private readonly PerforAgtempRepository perforAgtempRepository;
        private readonly PerforAgtempitemRepository perforAgtempitemRepository;
        private readonly PerforAgfixatitemRepository perforAgfixatitemRepository;
        private readonly PerforAgusetempRepository perforAgusetempRepository;
        private readonly PerforAgcomputeRepository perforAgcomputeRepository;
        private readonly PerforCofagainRepository perforCofagainRepository;
        private readonly PerforAgothersourceRepository perforAgothersourceRepository;
        private readonly PerforAgworkloadtypeRepository perforAgworkloadtypeRepository;
        private readonly PerforRoleRepository roleRepository;
        private readonly PerforResspecialunitRepository resspecialunitRepository;
        private readonly PersonService personService;
        private readonly PerforRescomputeRepository rescomputeRepository;
        private readonly List<ag_tempitem> tempitems = new List<ag_tempitem>();

        public SecondAllotService(IOptions<Application> application,
            PerforUserRepository perforUserRepository,
            PerforUserhospitalRepository perforUserhospitalRepository,
            PerforPerallotRepository perforPerallotRepository,
            PerforAgsecondallotRepository perforAgsecondallotRepository,
            PerforResaccountRepository perforResaccountRepository,
            PerforUserroleRepository userroleRepository,
            PerforAgworkloadRepository perforAgworkloadRepository,
            PerforAgtempRepository perforAgtempRepository,
            PerforAgtempitemRepository perforAgtempitemRepository,
            PerforAgfixatitemRepository perforAgfixatitemRepository,
            PerforAgusetempRepository perforAgusetempRepository,
            PerforAgcomputeRepository perforAgcomputeRepository,
            PerforCofagainRepository perforCofagainRepository,
            PerforAgothersourceRepository perforAgothersourceRepository,
            PerforAgworkloadtypeRepository perforAgworkloadtypeRepository,
            PerforRoleRepository roleRepository,
            PerforResspecialunitRepository resspecialunitRepository,
            PersonService personService,
            PerforRescomputeRepository rescomputeRepository)
        {
            this.application = application.Value;
            this.perforUserRepository = perforUserRepository;
            this.perforUserhospitalRepository = perforUserhospitalRepository;
            this.perforPerallotRepository = perforPerallotRepository;
            this.perforAgsecondallotRepository = perforAgsecondallotRepository;
            this.perforResaccountRepository = perforResaccountRepository;
            this.userroleRepository = userroleRepository;
            this.perforAgworkloadRepository = perforAgworkloadRepository;
            this.perforAgtempRepository = perforAgtempRepository;
            this.perforAgtempitemRepository = perforAgtempitemRepository;
            this.perforAgfixatitemRepository = perforAgfixatitemRepository;
            this.perforAgusetempRepository = perforAgusetempRepository;
            this.perforAgcomputeRepository = perforAgcomputeRepository;
            this.perforCofagainRepository = perforCofagainRepository;
            this.perforAgothersourceRepository = perforAgothersourceRepository;
            this.perforAgworkloadtypeRepository = perforAgworkloadtypeRepository;
            this.roleRepository = roleRepository;
            this.resspecialunitRepository = resspecialunitRepository;
            this.personService = personService;
            this.rescomputeRepository = rescomputeRepository;
            this.tempitems = perforAgtempitemRepository.GetEntities();
        }

        #region 二次绩效列表与数据保存
        /// <summary>
        /// 获取二次绩效列表
        /// </summary>
        /// <param name="userId"></param>
        /// <returns></returns>
        public List<SecondListResponse> GetSecondList(int userId)
        {
            var user = perforUserRepository.GetEntity(t => t.ID == userId);
            if (user == null)
                throw new NotImplementedException("人员ID无效");
            var userrole = userroleRepository.GetEntity(t => t.UserID == userId);
            var role = roleRepository.GetEntity(t => t.ID == userrole.RoleID);
            var hospital = perforUserhospitalRepository.GetEntity(t => t.UserID == userId);
            if (hospital == null)
                throw new NotImplementedException("人员未选择医院");
            var allotList = perforPerallotRepository.GetEntities(t => t.HospitalId == hospital.HospitalID && new List<int> { 6, 8 }.Contains(t.States));
            if (allotList == null || allotList.Count == 0)
                throw new NotImplementedException("该医院未生成绩效");

            var allotListId = allotList.Select(t => t.ID).ToList();
            Expression<Func<ag_secondallot, bool>> exp = t => allotListId.Contains(t.AllotId.Value) && t.Department == user.Department;
            if (role.Type == application.DirectorRole)
                exp = exp.And(t => new List<string> { UnitType.医生组.ToString(), UnitType.医技组.ToString() }.Contains(t.UnitType));
            else if (role.Type == application.NurseRole)
                exp = exp.And(t => t.UnitType == UnitType.护理组.ToString());
            else if (role.Type == application.SpecialRole)
                exp = exp.And(t => t.UnitType == UnitType.特殊核算组.ToString());

            var secondList = perforAgsecondallotRepository.GetEntities(exp);
            //各科室绩效分配结果
            var accountList = perforResaccountRepository.GetEntities(t => allotListId.Contains(t.AllotID.Value) && t.Department == user.Department);
            //取得未生成二次绩效的绩效id  
            var exceptListId = secondList == null ? allotListId : allotListId.Except(secondList.Select(t => t.AllotId.Value));

            var specialList = resspecialunitRepository.GetEntities(t => allotListId.Contains(t.AllotID.Value) && t.Department == user.Department);

            #region 初始化二次绩效
            List<ag_secondallot> newSecond = new List<ag_secondallot>();
            foreach (var item in exceptListId)
            {
                var allot = allotList.FirstOrDefault(t => t.ID == item);
                if (allot == null) continue;

                res_account account = null;
                res_specialunit special = null;
                if (role.Type == application.DirectorRole)
                    account = accountList?.FirstOrDefault(t => t.AllotID == item && (t.UnitType == (int)UnitType.医生组 || t.UnitType == (int)UnitType.医技组));
                else if (role.Type == application.NurseRole)
                    account = accountList?.FirstOrDefault(t => t.AllotID == item && t.UnitType == (int)UnitType.护理组);
                else if (role.Type == application.SpecialRole)
                    special = specialList?.FirstOrDefault(t => t.AllotID == item);

                if (account == null && special == null) continue;

                var second = new ag_secondallot
                {
                    AllotId = item,
                    Year = allot.Year,
                    Month = allot.Month,
                    Department = user.Department,
                    UnitType = role.Type == application.SpecialRole ? UnitType.特殊核算组.ToString() : ((UnitType)account.UnitType).ToString(),
                    RealGiveFee = role.Type == application.SpecialRole ? special.RealGiveFee : account.RealGiveFee,
                    Status = 1
                };
                newSecond.Add(second);
            }
            #endregion

            if (newSecond.Count > 0)
            {
                perforAgsecondallotRepository.AddRange(newSecond.ToArray());
                if (secondList == null)
                    secondList = newSecond;
                else
                    secondList.AddRange(newSecond);
            }

            var list = Mapper.Map<List<SecondListResponse>>(secondList);
            list?.ForEach(t => t.IsArchive = allotList.FirstOrDefault(a => a.ID == t.AllotId).States == 8 ? 1 : 0);
            return list;
        }

        #region 二次绩效详情

        ///// <summary>
        ///// 二次绩效详情
        ///// </summary>
        ///// <returns></returns>
        //public SecondResponse GetSecondDetail(UseTempRequest request)
        //{
        //    var usetemp = perforAgusetempRepository.GetEntity(t => t.HospitalId == request.HospitalId && t.Department == request.Department && t.UnitType == request.UnitType);
        //    if (usetemp == null)
        //        throw new PerformanceException("当前科室暂未配置绩效模板");

        //    var second = perforAgsecondallotRepository.GetEntity(t => t.Id == request.SecondId);
        //    //获取固定模板列 + 工作量列
        //    var headItems = GetHeadItems(usetemp.UseTempId.Value, usetemp.HospitalId.Value, usetemp.Department, usetemp.UnitType);

        //    var result = new SecondResponse { HeadItems = headItems, BodyItems = new List<BodyItem>() };
        //    //获取已录入数据
        //    var fixatList = perforAgfixatitemRepository.GetEntities(t => t.SecondId == request.SecondId && t.RowNumber.HasValue);
        //    if (request.IsArchive == 1 || new List<int> { 2, 3 }.Contains(second.Status ?? 1))     //归档  等待审核、审核通过
        //    {
        //        #region 已归档数据，根据数据获取 列
        //        if (fixatList == null || fixatList.Where(t => t.RowNumber != -1).Count() == 0)
        //            throw new PerformanceException("提交时未添加数据。");
        //        else
        //        {
        //            var existHead = fixatList.Select(t => new { FiledName = t.ItemName, Sort = t.Sort.Value, SourceType = t.SourceType.Value, Type = t.Type.Value, FactorValue = t.FactorValue.Value }).Distinct().ToList();
        //            headItems = existHead.Select(t => new HeadItem
        //            {
        //                FiledId = headItems.FirstOrDefault(h => h.FiledName == t.FiledName && h.Type == t.Type)?.FiledId ?? "无FiledId",
        //                FiledName = t.FiledName,
        //                Sort = headItems.FirstOrDefault(h => h.FiledName == t.FiledName && h.Type == t.Type)?.Sort ?? 0,
        //                SourceType = t.SourceType,
        //                Type = t.Type,
        //                FactorValue = headItems.FirstOrDefault(h => h.FiledName == t.FiledName && h.Type == t.Type)?.FactorValue ?? 0
        //            }).ToList();
        //            result.HeadItems = headItems;
        //        }
        //        #endregion
        //    }
        //    //未归档
        //    if (fixatList != null && fixatList.Where(t => t.RowNumber != -1).Count() > 0)
        //    {
        //        var rows = fixatList.Select(t => t.RowNumber.Value).Distinct();
        //        foreach (var row in rows)
        //        {
        //            var header = row == -1 ? headItems.Where(t => t.Type == 1).ToList() : headItems.Where(t => t.Type != 1).ToList();
        //            result.BodyItems.AddRange(GetBodyItems(header, 2, fixatitems: fixatList, row: row));
        //        }
        //    }
        //    else if (fixatList == null || (fixatList != null && fixatList.Where(t => t.RowNumber != -1).Count() == 0))
        //    {
        //        #region 补充历史绩效需要带出的数据
        //        var bringhead = headItems.Where(t => t.IsBring == 1).ToList();
        //        if (bringhead != null && bringhead.Count > 0)
        //        {
        //            var allotIds = perforPerallotRepository.GetEntities(t => t.HospitalId == request.HospitalId).Select(a => a.ID);
        //            var secondIdList = perforAgsecondallotRepository.GetEntities(t => allotIds.Contains(t.AllotId.Value)
        //            && t.Department == request.Department && t.UnitType == request.UnitType)
        //                .OrderBy(t => t.Year).ThenBy(t => t.Month).Select(t => t.Id).ToList();
        //            var index = secondIdList.IndexOf(request.SecondId);
        //            if (index != 0)
        //                fixatList = perforAgfixatitemRepository.GetEntities(t => t.SecondId == secondIdList.ElementAt(index - 1) && t.RowNumber.HasValue);

        //            fixatList = fixatList?.Where(t => bringhead.Select(h => h.FiledName).Contains(t.ItemName)).ToList();
        //            if (fixatList != null && fixatList.Count > 0)
        //            {
        //                var rows = fixatList.Select(t => t.RowNumber.Value).Distinct();
        //                foreach (var row in rows)
        //                {
        //                    var header = row == -1 ? bringhead.Where(t => t.Type == 1).ToList() : bringhead.Where(t => t.Type != 1).ToList();
        //                    result.BodyItems.AddRange(GetBodyItems(header, 2, fixatitems: fixatList, row: row));
        //                }
        //            }
        //        }
        //        #endregion
        //    }
        //    if (fixatList == null || (fixatList != null && fixatList.Where(t => t.RowNumber == -1).Count() == 0))
        //    {
        //        var config = perforCofagainRepository.GetEntities(t => t.AllotID == second.AllotId && t.Department == request.Department) ?? new List<cof_again>();

        //        #region 补充顶部数据
        //        config.Add(new cof_again { TypeName = "绩效合计(考核后)", Value = second.RealGiveFee });
        //        result.BodyItems.AddRange(GetBodyItems(headItems.Where(t => t.Type == 1).ToList(), 1, configs: config));
        //        result.BodyItems.FirstOrDefault(t => t.FiledName == "发放月份").Value = $"{second.Year}年{second.Month}月";
        //        #endregion
        //    }
        //    return new SecondResponse
        //    {
        //        HeadItems = result.HeadItems.OrderBy(t => t.Type).ThenBy(t => t.Sort).ThenBy(t => t.FiledName).ToList(),
        //        BodyItems = result.BodyItems.OrderBy(t => t.RowNumber).ThenBy(t => t.Type).ThenBy(t => t.Sort).ToList(),
        //    };
        //}

        ///// <summary>
        ///// 二次绩效详情
        ///// </summary>
        ///// <returns></returns>
        //public List<ag_othersource> GetSecondDetail(int secondid)
        //{
        //    var others = perforAgothersourceRepository.GetEntities(t => t.SecondId == secondid);
        //    return others;
        //}

        #endregion

        #region 二次绩效详情-使用中
        /// <summary>
        /// 二次绩效详情
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public SecondResponse GetSecondDetail(UseTempRequest request, int userId)
        {
            var usetemp = perforAgusetempRepository.GetEntity(t => t.HospitalId == request.HospitalId
            && t.Department == request.Department && t.UnitType == request.UnitType);   //获取科室二次绩效费用分配使用的模板
            if (usetemp == null)
                throw new PerformanceException("当前科室暂未配置绩效模板");


            var temp = perforAgtempRepository.GetEntity(t => t.Id == usetemp.UseTempId);
            if (temp == null || temp.IsEnable != 1)
                throw new PerformanceException("模板无效，请重新选择");

            var second = perforAgsecondallotRepository.GetEntity(t => t.Id == request.SecondId);
            //获取固定模板列 + 工作量列
            var headItems = GetHeadItems(request.TempId, usetemp.HospitalId.Value, usetemp.Department, usetemp.UnitType);

            var result = new SecondResponse();

            var fixatList = perforAgfixatitemRepository.GetEntities(t => t.SecondId == request.SecondId && t.RowNumber.HasValue);
            //归档 或 等待审核、审核通过时，headItems不会随选择模板改动，带出已填写数据中的headItems
            if (request.IsArchive == 1 || new List<int> { 2, 3 }.Contains(second.Status ?? 1))
            {
                if (fixatList == null || fixatList.Where(t => t.RowNumber != -1).Count() == 0)
                    throw new PerformanceException("提交时未添加数据。");

                result = SubmittedData(fixatList, headItems);
            }
            else
            {
                result = new SecondResponse { HeadItems = headItems };
                //判断是否有数据
                //有数据 带出历史数据
                if (fixatList != null && fixatList.Any())
                {
                    result.BodyItems = GetBodyItems(fixatList, headItems);
                    if (fixatList.Where(t => t.RowNumber != -1) == null || !fixatList.Where(t => t.RowNumber != -1).Any())
                        result.BodyItems.AddRange(GetEmployees(second.AllotId.Value, userId, headItems));   //更换模板时，会自动保存顶部数据
                }
                else
                {
                    //无数据 根据IsBring带出历史二次绩效中需要带出的数据
                    //result.BodyItems = GetBringItems(request, headItems);
                    result.BodyItems = GetEmployees(second.AllotId.Value, userId, headItems);

                    var bodys = Mapper.Map<List<BodyItem>>(headItems.Where(t => t.Type == 1));
                    if (bodys != null && bodys.Any())
                        bodys.ForEach(t => t.RowNumber = -1);
                    result.BodyItems.AddRange(bodys);
                }
            }

            //检验 二次绩效配置 数据是否 有值，无则补充带出
            FillData(second, result.BodyItems);

            SupplyHeaderByWorkItem(request, result, second, fixatList?.Where(t => t.RowNumber == -1));

            return new SecondResponse
            {
                HeadItems = result.HeadItems.OrderBy(t => t.Type).ThenBy(t => t.WorkType).ThenBy(t => t.Sort).ThenBy(t => t.FiledName).ToList(),
                BodyItems = result.BodyItems.OrderBy(t => t.RowNumber).ThenBy(t => t.Type).ThenBy(t => t.Sort).ToList(),
            };
        }

        private List<BodyItem> GetEmployees(int allotId, int userId, List<HeadItem> heads)
        {
            var list = new List<BodyItem>();

            var employees = personService.GetPersons(allotId, userId);
            if (employees == null || !employees.Any()) return list;

            Dictionary<(string, string), Func<per_employee, object>> dict = new Dictionary<(string, string), Func<per_employee, object>>
            {
                { ("姓名", "FullName"), (t) => t.DoctorName },
                { ("岗位", "Post"), (t) => !string.IsNullOrEmpty(t.Duty) && (t.Duty.IndexOf("主任") > -1 || t.Duty.IndexOf("护士长") > -1) ? "主任" : "其他" },
                { ("出勤", "ActualAttendance"), (t) => t.AttendanceDay },
            };

            int rowNumber = 1;
            foreach (var employee in employees)
            {
                foreach (var item in dict)
                {
                    var head = heads.FirstOrDefault(t => t.FiledName == item.Key.Item1 && t.FiledId == item.Key.Item2);
                    if (head != null)
                    {
                        var body = Mapper.Map<BodyItem>(head);
                        body.Value = item.Value.Invoke(employee)?.ToString();
                        body.RowNumber = rowNumber;
                        list.Add(body);
                    }
                }
                rowNumber++;
            }

            return list;
        }

        /// <summary>
        /// 根据已保存的数据返回
        /// </summary>
        /// <param name="fixatitems">已保存的数据</param>
        /// <param name="headItems">列的名称、系数等值</param>
        /// <returns></returns>
        private SecondResponse SubmittedData(List<ag_fixatitem> fixatitems, List<HeadItem> headItems)
        {
            var header = fixatitems.Select(t => new { t.ItemName, t.Type, t.Sort }).ToDistinct().ToList();

            var result = new SecondResponse
            {
                HeadItems = header.Select(t => new HeadItem
                {
                    FiledId = headItems.FirstOrDefault(h => h.FiledName == t.ItemName && h.Type == t.Type)?.FiledId ?? t.ItemName + t.Type,
                    FiledName = t.ItemName,
                    Sort = t.Sort.Value,
                    Type = t.Type.Value,
                    FactorValue = headItems.FirstOrDefault(h => h.FiledName == t.ItemName && h.Type == t.Type)?.FactorValue ?? 0
                }).ToList()
            };
            result.BodyItems = GetBodyItems(fixatitems, headItems);
            return result;
        }

        /// <summary>
        /// 获取历史数据
        /// </summary>
        /// <param name="fixatitems"></param>
        /// <param name="headItems"></param>
        /// <returns></returns>
        private List<BodyItem> GetBodyItems(List<ag_fixatitem> fixatitems, List<HeadItem> headItems)
        {
            var bodyItems = new List<BodyItem>();
            if (fixatitems != null && fixatitems.Any())
            {
                bodyItems = fixatitems.Select(t => new BodyItem
                {
                    RowNumber = t.RowNumber.Value,
                    FiledId = tempitems.FirstOrDefault(h => h.FiledName == t.ItemName && h.Type == t.Type)?.FiledId ??
                    headItems.FirstOrDefault(h => h.FiledName == t.ItemName && h.Type == t.Type)?.FiledId,
                    FiledName = t.ItemName,
                    SourceType = t.SourceType ?? 0,
                    Type = t.Type ?? 0,
                    Value = t.ItemValue,
                    Sort = t.Sort ?? 0,
                    SpecialAttr = t.SpecialAttr ?? headItems.FirstOrDefault(h => h.FiledName == t.ItemName && h.Type == t.Type)?.SpecialAttr,
                }).ToList();
            }
            // 删除多余的headvalue
            bodyItems.RemoveAll(t => !headItems.Select(h => h.FiledId).Contains(t.FiledId) && t.RowNumber == -1);
            return bodyItems;
        }

        /// <summary>
        /// 补充须带出的历史数据，如姓名、职称等
        /// </summary>
        /// <param name="request"></param>
        /// <param name="headItems"></param>
        /// <returns></returns>
        private List<BodyItem> GetBringItems(UseTempRequest request, List<HeadItem> headItems)
        {
            var bodyItems = new List<BodyItem>();
            var bringhead = headItems.Where(t => t.IsBring == 1).ToList();
            if (bringhead != null && bringhead.Count > 0)
            {
                var allotIds = perforPerallotRepository.GetEntities(t => t.HospitalId == request.HospitalId).Select(a => a.ID);
                var secondIdList = perforAgsecondallotRepository.GetEntities(t => allotIds.Contains(t.AllotId.Value)
                && t.Department == request.Department && t.UnitType == request.UnitType)
                    .OrderBy(t => t.Year).ThenBy(t => t.Month).Select(t => t.Id).ToList();
                var index = secondIdList.IndexOf(request.SecondId);
                var fixatList = new List<ag_fixatitem>();
                if (index != 0)
                    fixatList = perforAgfixatitemRepository.GetEntities(t => t.SecondId == secondIdList.ElementAt(index - 1)
                    && t.RowNumber.HasValue && t.RowNumber != -1 && bringhead.Select(s => s.FiledName).Contains(t.ItemName));

                if (fixatList != null && fixatList.Any())
                    bodyItems = GetBodyItems(fixatList, headItems);
            }
            return bodyItems;
        }

        /// <summary>
        /// 补充二次绩效配置数据
        /// </summary>
        /// <param name="second"></param>
        /// <param name="bodyItems"></param>
        private void FillData(ag_secondallot second, List<BodyItem> bodyItems)
        {
            if (bodyItems == null || !bodyItems.Any()) return;

            var account = perforResaccountRepository.GetEntity(t => t.AllotID == second.AllotId && t.AccountingUnit == second.Department && ((UnitType)t.UnitType).ToString() == second.UnitType);

            var keyValue = new Dictionary<string, string>
            {
                {"发放月份",  $"{second.Year}年{second.Month.ToString().PadLeft(2, '0')}月"},
                {"可分配绩效",  second.RealGiveFee.ToString()},
                //{"主任基础绩效", account?.Avg?.ToString()}
            };
            var pairs = new Dictionary<string, string>
            {
                {  "职称绩效", "年资职称绩效占比" },
                {  "工作量绩效", "工作量绩效占比" },
            };
            var config = perforCofagainRepository.GetEntities(t => t.AllotID == second.AllotId);
            if (config != null && config.Any())
                config.ForEach(t =>
                {
                    var key = pairs.ContainsKey(t.TypeName) ? pairs[t.TypeName] : t.TypeName;
                    if (!keyValue.Keys.Contains(key))
                        keyValue.Add(key, t.Value.ToString());
                });

            foreach (var item in keyValue)
            {
                var header = bodyItems.FirstOrDefault(t => t.FiledName == item.Key);
                if (header != null && (string.IsNullOrEmpty(header.Value) || header.Value == "0"))
                    bodyItems.FirstOrDefault(t => t.FiledName == item.Key).Value = item.Value;
            }
        }

        /// <summary>
        /// 根绝添加工作量类型判断是否添加
        /// </summary>
        /// <param name="request"></param>
        /// <param name="result"></param>
        private void SupplyHeaderByWorkItem(UseTempRequest request, SecondResponse result, ag_secondallot second, IEnumerable<ag_fixatitem> fixatitems)
        {
            //var workitem = perforAgworkloadRepository.GetEntities(t => t.HospitalId == request.HospitalId && t.Department == request.Department
            //&& t.UnitType == request.UnitType && t.WorkTypeId != (int)AgWorkloadType.SingleAwards);

            //if (workitem == null || !workitem.Any(t => t.Id > 0))
            //    return;

            //不包含工作量绩效
            if (!result.HeadItems.Select(t => t.FiledId).Contains("PerformanceShareTheWorkload"))
                return;

            var maxSortValue = result.HeadItems.Where(t => t.Type == 1).Max(t => t.Sort);

            var headers = new HeadItem[] {
                new HeadItem
                {
                    FiledId = "ThePerformanceOf",
                    Type =  1,
                    SourceType = 1,
                    IsBring =  2,
                    SpecialAttr = 1,
                },
                new HeadItem
                {
                    FiledId = "ThePerformanceAmountOf",
                    Type =  1,
                    SourceType = 1,
                    IsBring =  2,
                    SpecialAttr = 2,
                }
            };

            var headerItems = new List<HeadItem>();

            var unit = second.UnitType == UnitType.医技组.ToString() ? UnitType.医生组.ToString() : second.UnitType;
            var deptHeader = perforAgworkloadtypeRepository.GetEntities(t => request.HospitalId == t.HospitalId && t.Department == second.Department && t.UnitType == unit);
            if (deptHeader != null && deptHeader.Any())
            {
                int sortindex = 1;
                foreach (var item in deptHeader)
                {
                    if (item.HospitalId == 0) continue;

                    for (int i = 0; i < headers.Length; i++)
                    {
                        var headItem = (HeadItem)headers[i].Clone();
                        headItem.FiledName = (i % 2 == 0) ? item.TypeName : item.TypeName.Replace("占比", "金额");
                        if (i % 2 != 0 && !headItem.FiledName.EndsWith("金额"))
                            headItem.FiledName += "金额";
                        headItem.FiledId += item.Id;
                        headItem.Sort = maxSortValue + sortindex;
                        headItem.WorkType = item.Id;
                        headerItems.Add(headItem);
                        sortindex++;
                    }
                }
            }
            var defauleHeader = new List<ag_workload_type>
            {
                new ag_workload_type { Id = 2, TypeName = "工作量绩效占比", },
                new ag_workload_type { Id = 2, TypeName = "工作量分配绩效金额" },
            };
            foreach (var item in defauleHeader)
            {
                result.HeadItems.Where(t => t.FiledName == item.TypeName).ToList()?.ForEach(t =>
                {
                    t.WorkType = item.Id;
                    t.SpecialAttr = item.TypeName.IndexOf("占比") > -1 ? 1 : 2;
                });
                result.BodyItems.Where(t => t.FiledName == item.TypeName).ToList()?.ForEach(t =>
                {
                    t.WorkType = item.Id;
                    t.SpecialAttr = item.TypeName.IndexOf("占比") > -1 ? 1 : 2;
                });
            }

            var rownumber = result.BodyItems.Any(t => t.RowNumber == -1) ? -1 : 0;
            foreach (var item in headerItems)
            {
                if (!result.HeadItems.Select(t => t.FiledId).Contains(item.FiledId))
                {
                    result.HeadItems.Add(item);
                    var body = Mapper.Map<BodyItem>(item);
                    body.RowNumber = rownumber;
                    if (fixatitems != null && fixatitems.Any(t => t.ItemName == item.FiledName))
                        body.Value = fixatitems.FirstOrDefault(t => t.ItemName == item.FiledName).ItemValue;
                    result.BodyItems.Add(body);
                }
            }
        }
        #endregion

        /// <summary>
        /// 二次绩效项录入保存
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public bool SaveValue(List<ag_fixatitem> request)
        {
            var secondId = request.First().SecondId;
            var second = perforAgsecondallotRepository.GetEntity(t => t.Id == secondId);
            if (second == null)
                throw new PerformanceException("二次绩效ID不存在");

            var fixatitems = perforAgfixatitemRepository.GetEntities(t => t.SecondId == secondId);
            var result = DelValue(fixatitems, request);
            List<ag_fixatitem> update = new List<ag_fixatitem>(), insert = new List<ag_fixatitem>();
            if (fixatitems != null && fixatitems.Any())
            {
                foreach (var item in request)
                {
                    if (fixatitems.Any(t => t.RowNumber == item.RowNumber && t.ItemName == item.ItemName))
                    {
                        var cellItem = fixatitems.FirstOrDefault(t => t.RowNumber == item.RowNumber && t.ItemName == item.ItemName);
                        if (cellItem == null)
                            continue;
                        cellItem.ItemValue = item.ItemValue;
                        cellItem.Sort = item.Sort;
                        cellItem.SourceType = item.SourceType;
                        cellItem.Type = item.Type;
                        cellItem.UnitType = item.UnitType;
                        cellItem.SpecialAttr = item.SpecialAttr;
                        update.Add(cellItem);
                    }
                    else
                    {
                        insert.Add(item);
                    }
                }
            }
            else
                insert = request;
            result = perforAgfixatitemRepository.UpdateRange(update.ToArray());
            result = perforAgfixatitemRepository.AddRange(insert.ToArray());
            return result;
        }

        /// <summary>
        /// 删除未保存的历史数据
        /// </summary>
        /// <param name="fixatlist">数据库中查询到的值</param>
        /// <param name="fixatitems">需要保存的数据</param>
        /// <returns></returns>
        public bool DelValue(List<ag_fixatitem> fixatlist, List<ag_fixatitem> fixatitems)
        {
            var result = true;
            // 提交数据为空时，删除所有数据
            if (fixatitems == null || fixatitems.Count == 0)
            {
                if (fixatlist != null && fixatlist.Any())
                    result = perforAgfixatitemRepository.RemoveRange(fixatlist.ToArray());
                return result;
            }

            if (fixatlist != null && fixatlist.Any())
            {
                var groupData = fixatlist.GroupBy(t => new { t.RowNumber, t.ItemName }).Select(t => new
                {
                    t.Key.RowNumber,
                    t.Key.ItemName,
                    Count = t.Count(),
                    Id = t.Max(group => group.ID)
                });
                // 删除重复数据
                if (groupData.Any(t => t.Count > 1))
                {
                    var delData = fixatlist.Where(t => !groupData.Select(w => w.Id).Contains(t.ID));
                    int flag = fixatlist.RemoveAll(t => !groupData.Select(w => w.Id).Contains(t.ID));
                    result = perforAgfixatitemRepository.RemoveRange(delData.ToArray());
                }

                // 删除行号不存在的数据
                var saveRows = fixatitems.Select(t => t.RowNumber).Distinct();
                var delRows = fixatlist.Select(t => t.RowNumber).Distinct().Except(saveRows);
                if (delRows != null && delRows.Count() > 0)
                    result = perforAgfixatitemRepository.RemoveRange(fixatlist.Where(t => delRows.Contains(t.RowNumber)).ToArray());
            }

            return result;
        }

        /// <summary>
        /// 二次绩效分配结果保存
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public bool SaveCompute(List<ag_compute> request)
        {
            var secondId = request.First().SecondId;
            var second = perforAgsecondallotRepository.GetEntity(t => t.Id == secondId);
            if (second == null)
                throw new PerformanceException("二次绩效ID不存在");
            if (second.Status == 2)
                throw new PerformanceException("二次绩效已提交，无法重复提交");

            var compute = perforAgcomputeRepository.GetEntities(t => t.SecondId == secondId);
            foreach (var item in request)
            {
                if (compute != null && compute.Any(t => t.SecondId == secondId && t.Department == item.Department && t.PersonName == item.PersonName))
                {
                    var cellItem = compute.First(t => t.SecondId == secondId && t.Department == item.Department && t.PersonName == item.PersonName);
                    cellItem.RealGiveFee = item.RealGiveFee;
                    perforAgcomputeRepository.Update(cellItem);
                }
                else
                {
                    perforAgcomputeRepository.Add(item);
                }
            }
            return true;
        }
        #endregion

        #region 模板
        /// <summary>
        /// 获取模板列表
        /// </summary>
        /// <param name="userId"></param>
        /// <returns></returns>
        public List<SecondTempResponse> GetTemp(int hospitalid, string department, int userId)
        {
            var temps = perforAgtempRepository.GetEntities(t => t.IsEnable == 1);
            if (temps != null && temps.Any())
            {
                var userrole = userroleRepository.GetEntity(t => t.UserID == userId);
                var role = roleRepository.GetEntity(t => t.ID == userrole.RoleID);
                Expression<Func<ag_usetemp, bool>> exp = t => t.HospitalId == hospitalid && t.Department == department;
                if (role.Type == application.DirectorRole)
                    exp = exp.And(t => new List<string> { UnitType.医生组.ToString(), UnitType.医技组.ToString() }.Contains(t.UnitType));
                else if (role.Type == application.NurseRole)
                    exp = exp.And(t => t.UnitType == UnitType.护理组.ToString());

                var useTemp = perforAgusetempRepository.GetEntity(exp);
                var secondTemps = Mapper.Map<List<SecondTempResponse>>(temps);
                if (useTemp != null)
                    secondTemps.ForEach(t => t.IsSelected = t.Id == useTemp.UseTempId);
                return secondTemps;
            }
            return new List<SecondTempResponse>();
        }

        /// <summary>
        /// 使用模板
        /// </summary>
        /// <param name="tempId"></param>
        /// <returns></returns>
        public bool UseTemp(UseTempRequest request)
        {
            var result = false;
            var entity = perforAgusetempRepository.GetEntity(t => t.HospitalId == request.HospitalId
            && t.Department == request.Department && t.UnitType == request.UnitType);
            if (entity == null)
            {
                entity = Mapper.Map<ag_usetemp>(request);
                result = perforAgusetempRepository.Add(entity);
            }
            else
            {
                entity.UseTempId = request.TempId;
                result = perforAgusetempRepository.Update(entity);
                if (result)
                {
                    //获取固定模板列 + 工作量列
                    var headItems = GetHeadItems(request.TempId, request.HospitalId, request.Department, request.UnitType);

                    List<ag_fixatitem> list = new List<ag_fixatitem>();
                    var addList = new List<ag_fixatitem>();

                    var allotList = perforPerallotRepository.GetEntities(t => t.HospitalId == request.HospitalId);
                    var seconds = perforAgsecondallotRepository.GetEntities(t => allotList.Select(a => a.ID).Contains(t.AllotId.Value) && new List<int> { 1, 4 }.Contains(t.Status ?? 1));
                    var secondList = Mapper.Map<List<SecondListResponse>>(seconds);
                    secondList?.ForEach(t => t.IsArchive = allotList.FirstOrDefault(a => a.ID == t.AllotId).States == 8 ? 1 : 0);

                    //获取未归档  未提交  驳回 的二次绩效
                    var secondId = secondList.Where(s => s.IsArchive == 0)?.Select(s => s.Id);
                    if (secondId == null || secondId.Count() <= 0)
                        return result;

                    var fixatList = perforAgfixatitemRepository.GetEntities(t => secondId.Contains(t.SecondId.Value));

                    #region 获取需要添加的数据 和 无需操作的数据
                    //var update_second_usetemps = new List<ag_secondallot>();
                    foreach (var second in secondList)
                    {
                        if (second.IsArchive == 0 && new List<int> { 1, 4 }.Contains(second.Status ?? 1))
                        {
                            //var update_second_usetemp = seconds.FirstOrDefault(t => t.Id == second.Id);
                            //update_second_usetemp.UseTempId = request.TempId;
                            //update_second_usetemps.Add(update_second_usetemp);

                            foreach (var head in headItems)
                            {
                                var exist = fixatList?.Where(t => t.ItemName == head.FiledName && t.Type == head.Type && t.SecondId == second.Id);
                                if (exist != null && exist.Count() > 0)
                                    list.AddRange(exist);
                                else if (head.Type == 1)
                                {
                                    var configs = perforCofagainRepository.GetEntities(t => t.AllotID == second.AllotId && t.Department == request.Department) ?? new List<cof_again>();
                                    addList.Add(new ag_fixatitem
                                    {
                                        ItemName = head.FiledName,
                                        RowNumber = -1,
                                        Type = head.Type,
                                        SourceType = head.SourceType,
                                        Sort = head.Sort,
                                        FactorValue = head.FactorValue,
                                        UnitType = second.UnitType,
                                        AllotId = second.AllotId,
                                        SecondId = second.Id,
                                        ItemValue = head.FiledName == "绩效合计(考核后)" ? second.RealGiveFee?.ToString()
                                        : head.FiledName == "发放月份" ? $"{second.Year}年{second.Month.ToString().PadLeft(2, '0')}月"
                                        : configs.FirstOrDefault(t => t.TypeName == head.FiledName)?.Value.ToString()
                                    });
                                }
                            }
                        }
                    }
                    #endregion
                    //perforAgsecondallotRepository.UpdateRange(update_second_usetemps.ToArray());
                    if (list != null && list.Count > 0)
                    {
                        var delList = fixatList.Except(list);
                        perforAgfixatitemRepository.RemoveRange(delList.ToArray());

                        if (addList != null && addList.Count > 0)
                            perforAgfixatitemRepository.AddRange(addList.ToArray());
                    }
                }
            }
            return result;
        }

        /// <summary>
        /// 应用模板
        /// </summary>
        /// <returns></returns>
        public void RefreshTemp(UseTempRequest request)
        {
            var usetemp = perforAgusetempRepository.GetEntity(t => t.HospitalId == request.HospitalId && t.Department == request.Department && t.UnitType == request.UnitType);
            if (usetemp == null)
                throw new PerformanceException("参数usetempId 无效");
            //获取工作量列头
            var workItem = perforAgworkloadRepository.GetEntities(t => t.HospitalId == usetemp.HospitalId && t.Department == usetemp.Department && t.UnitType == usetemp.UnitType);
            //获取固定模板列头
            var tempItem = perforAgtempitemRepository.GetEntities(t => t.TempId == usetemp.UseTempId);
            var tempHeader = workItem == null ? tempItem.Select(t => t.FiledName) : tempItem.Select(t => t.FiledName).Union(workItem?.Select(t => t.ItemName));

            //获取数据
            var fixatList = perforAgfixatitemRepository.GetEntities(t => t.SecondId == request.SecondId);
            if (fixatList == null || fixatList.Count == 0)
                throw new PerformanceException("未录入数据");

            //更新系数、排序
            fixatList.ForEach(t =>
            {
                t.Sort = workItem?.FirstOrDefault(w => w.ItemName == t.ItemName)?.Sort;
                t.FactorValue = workItem?.FirstOrDefault(w => w.ItemName == t.ItemName)?.FactorValue;
            });
            perforAgfixatitemRepository.UpdateRange(fixatList.ToArray());
            //删除  列 不存在的数据
            var header = fixatList.Select(t => t.ItemName).Distinct();
            var delItems = header.Except(tempHeader);
            if (delItems != null && delItems.Count() > 0)
                perforAgfixatitemRepository.RemoveRange(fixatList.Where(t => delItems.Contains(t.ItemName)).ToArray());
            //添加  新增列 的数据
            var addItems = new List<ag_fixatitem>();
            fixatList.Select(t => t.RowNumber).Distinct().ToList().ForEach(t =>
            {
                addItems.AddRange(tempHeader.Except(header)?.Select(s => new ag_fixatitem
                {
                    ItemName = s,
                    RowNumber = t,
                    AllotId = fixatList.First().AllotId,
                    SecondId = fixatList.First().SecondId,
                    UnitType = fixatList.First().UnitType,
                    Sort = tempItem?.FirstOrDefault(w => w.FiledName == s)?.Sort ?? workItem?.FirstOrDefault(w => w.ItemName == s)?.Sort,
                    FactorValue = workItem?.FirstOrDefault(w => w.ItemName == s)?.FactorValue,
                    Type = tempItem?.FirstOrDefault(w => w.FiledName == s)?.Type ?? 3,
                    SourceType = tempItem?.FirstOrDefault(w => w.FiledName == s)?.SourceType ?? 1,
                }));
            });
            if (addItems != null && addItems.Count() > 0)
                perforAgfixatitemRepository.AddRange(addItems.ToArray());
        }
        #endregion

        #region 工作量绩效配置
        /// <summary>
        /// 获取工作量列表
        /// </summary>
        /// <param name="secondId"></param>
        /// <returns></returns>
        public List<ag_workload> GetWorkloadList(WorkloadRequest request)
        {
            return perforAgworkloadRepository.GetEntities(t => t.HospitalId == request.HospitalId && t.Department == request.Department
            && t.UnitType == request.UnitType && t.WorkTypeId != (int)AgWorkloadType.SingleAwards);
        }

        /// <summary>
        /// 新增工作量绩效配置
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public bool WorkloadAdd(WorkloadRequest request)
        {
            var workloadList = perforAgworkloadRepository.GetEntities(t => t.HospitalId == request.HospitalId && t.Department == request.Department && t.UnitType == request.UnitType);
            if (workloadList != null && workloadList.Any(t => t.ItemName == request.ItemName))
                throw new PerformanceException("项目名称重复");
            ag_workload workload = new ag_workload
            {
                HospitalId = request.HospitalId,
                Department = request.Department,
                UnitType = request.UnitType,
                FactorValue = request.FactorValue ?? 1,
                ItemName = request.ItemName,
                Sort = request.Sort ?? 1,
                WorkTypeId = request.WorkTypeId,
            };
            var result = perforAgworkloadRepository.Add(workload);
            if (result)
            {
                workload.ItemId = $"Feild{workload.Id}";
                perforAgworkloadRepository.Update(workload);
            }

            return result;
        }

        /// <summary>
        /// 修改工作量绩效配置
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        public bool WorkloadUpdate(WorkloadRequest request)
        {
            var workloadList = perforAgworkloadRepository.GetEntities(t => t.HospitalId == request.HospitalId && t.Department == request.Department && t.UnitType == request.UnitType);
            if (workloadList != null && workloadList.Any(t => t.Id != request.Id && t.ItemName == request.ItemName))
                throw new PerformanceException("项目名称重复");

            var workload = workloadList.FirstOrDefault(t => t.Id == request.Id);
            workload.HospitalId = request.HospitalId;
            workload.Department = request.Department;
            workload.UnitType = request.UnitType;
            workload.FactorValue = request.FactorValue;
            workload.ItemName = request.ItemName;
            workload.Sort = request.Sort;
            workload.ItemId = $"Feild{workload.Id}";
            workload.WorkTypeId = request.WorkTypeId;

            return perforAgworkloadRepository.Update(workload);
        }

        /// <summary>
        /// 删除工作量绩效配置
        /// </summary>
        /// <param name="id"></param>
        /// <returns></returns>
        public bool WorkloadDelete(int id)
        {
            var workload = perforAgworkloadRepository.GetEntity(t => t.Id == id);
            return perforAgworkloadRepository.Remove(workload);
        }

        /// <summary>
        /// 获取单行奖励列表
        /// </summary>
        /// <param name="secondId"></param>
        /// <returns></returns>
        public List<ag_workload> GetSingleList(WorkloadRequest request)
        {
            return perforAgworkloadRepository.GetEntities(t => t.HospitalId == request.HospitalId && t.Department == request.Department
            && t.UnitType == request.UnitType && t.WorkTypeId == (int)AgWorkloadType.SingleAwards);
        }

        /// <summary>
        /// 获取工作量类型列表
        /// </summary>
        /// <param name="secondId"></param>
        /// <returns></returns>
        public List<TitleValue<int>> WorkTypeList(WorkloadRequest request, int userId)
        {
            var (unit, dept) = GetDeptAndUnit(userId);
            var worktypes = perforAgworkloadtypeRepository.GetEntities(t => request.HospitalId.Value == t.HospitalId && t.Department == dept && t.UnitType == unit);
            if (worktypes != null && worktypes.Any())
            {
                return worktypes.Select(t => new TitleValue<int>
                {
                    Title = t.TypeName,
                    Value = t.Id
                }).ToList();
            }
            return null;
        }

        /// <summary>
        /// 保存工作量类型
        /// </summary>
        /// <param name="secondId"></param>
        /// <returns></returns>
        public ag_workload_type SaveWorkType(ag_workload_type request, int userId)
        {
            var (unit, dept) = GetDeptAndUnit(userId);
            var entity = perforAgworkloadtypeRepository.GetEntity(t => request.HospitalId == t.HospitalId && t.Department == dept && t.UnitType == unit && t.TypeName == request.TypeName);
            if (entity == null)
            {
                if (request.Id > 0)
                {
                    entity = perforAgworkloadtypeRepository.GetEntity(t => t.Id == request.Id);
                    entity.HospitalId = request.HospitalId;
                    entity.TypeName = request.TypeName;

                    perforAgworkloadtypeRepository.Update(entity);
                }
                else
                {
                    entity = new ag_workload_type
                    {
                        HospitalId = request.HospitalId,
                        TypeName = request.TypeName,
                        Department = dept,
                        UnitType = unit,
                    };
                    perforAgworkloadtypeRepository.Add(entity);
                }
                return entity;
            }
            else if (request.Id != entity.Id)
                throw new PerformanceException("类型已存在");
            else
                return request;
        }

        /// <summary>
        /// 获取工作量类型列表
        /// </summary>
        /// <param name="secondId"></param>
        /// <returns></returns>
        public bool DeleteWorkType(WorkloadRequest request)
        {
            var entity = perforAgworkloadtypeRepository.GetEntity(t => t.Id == request.Id);
            if (entity != null)
            {
                return perforAgworkloadtypeRepository.Remove(entity);
            }
            else
                return false;
        }

        public (string, string) GetDeptAndUnit(int userId)
        {
            var user = perforUserRepository.GetEntity(t => t.ID == userId);
            var userrole = userroleRepository.GetEntity(t => t.UserID == userId);
            var role = roleRepository.GetEntity(t => t.ID == userrole.RoleID);

            if (role.Type == application.DirectorRole)
                return (UnitType.医生组.ToString(), user.Department);
            else if (role.Type == application.NurseRole)
                return (UnitType.护理组.ToString(), user.Department);
            else
                return ("", user.Department);
        }
        #endregion

        #region 二次绩效考核
        /// <summary>
        /// 二次绩效考核列表
        /// </summary>
        /// <param name="userId">用户ID</param>
        /// <returns></returns>
        public List<ag_secondallot> AuditList(int userId, int allotId)
        {
            //var hospital = perforUserhospitalRepository.GetEntities(t => t.UserID == userId);
            //var allotList = perforPerallotRepository.GetEntities(t => hospital.Select(h => h.HospitalID).Contains(t.HospitalId));
            //if (allotList != null && allotList.Count > 0)
            //{
            //    var allotIds = allotList.Select(t => t.ID);
            //    return perforAgsecondallotRepository.GetEntities(t => allotIds.Contains(t.AllotId.Value) && t.Status == 2);
            //}
            //return null;
            var allot = perforPerallotRepository.GetEntity(t => t.ID == allotId);
            if (allot == null)
                throw new PerformanceException("所选绩效不存在！");

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

        /// <summary>
        /// 提交审核
        /// </summary>
        /// <param name="userId">用户ID</param>
        /// <param name="secondId">二次绩效ID</param>
        /// <returns></returns>
        public bool AuditSubmit(ag_secondallot second, int userId)
        {
            var allot = perforPerallotRepository.GetEntity(t => t.ID == second.AllotId);
            if (allot == null)
                throw new PerformanceException("二次绩效无效！");

            var userrole = userroleRepository.GetEntity(t => t.UserID == userId);
            var role = roleRepository.GetEntity(t => t.ID == userrole.RoleID);

            Expression<Func<ag_usetemp, bool>> exp = t => t.HospitalId == allot.HospitalId && t.Department == second.Department;
            if (role.Type == application.DirectorRole)
                exp = exp.And(t => new List<string> { UnitType.医生组.ToString(), UnitType.医技组.ToString() }.Contains(t.UnitType));
            else if (role.Type == application.NurseRole)
                exp = exp.And(t => t.UnitType == UnitType.护理组.ToString());

            var temp = perforAgusetempRepository.GetEntity(exp);
            if (temp == null)
                throw new PerformanceException("选择模板不可用，请确定模板及数据是否存在！");
            if (temp.UseTempId == 6)
            {
                var data = perforAgothersourceRepository.GetEntities(t => t.SecondId == second.Id);
                if (data == null || !data.Any())
                    throw new PerformanceException("提交时未检测到数据!");
            }
            else
            {
                var data = perforAgfixatitemRepository.GetEntities(t => t.SecondId == second.Id);
                if (data == null || !data.Any())
                    throw new PerformanceException("提交时未检测到数据!");
            }
            second.UseTempId = temp.UseTempId;
            second.Status = 2;
            second.SubmitType = temp.UseTempId == 6 ? 2 : 1;
            second.SubmitTime = DateTime.Now;
            second.Remark = "已提交审核，等待审核中";
            return perforAgsecondallotRepository.Update(second);
        }

        /// <summary>
        /// 审核
        /// </summary>
        /// <param name="userId">用户ID</param>
        /// <param name="secondId">二次绩效ID</param>
        /// <param name="ispass">1、审核通过 2、驳回</param>
        /// <returns></returns>
        public bool ConfirmAudit(int userId, SecondAuditRequest request)
        {
            var second = perforAgsecondallotRepository.GetEntity(t => t.Id == request.SecondId);
            if (second.Status != 2)
                throw new PerformanceException("该绩效未提交至审核，请确认");

            if (request.IsPass == 1)
            {
                second.Status = 3;
            }
            else
            {
                second.UseTempId = null;
                second.Status = 4;
            }
            //second.Status = request.IsPass == 1 ? 3 : 4;
            second.AuditUser = userId;
            second.AuditTime = DateTime.Now;
            second.Remark = request.Remark;
            if (string.IsNullOrEmpty(second.Remark))
            {
                second.Remark = request.IsPass == 1 ? "审核通过" : "驳回";
            }
            var result = perforAgsecondallotRepository.Update(second);

            #region 添加至二次绩效汇总

            if (result && request.IsPass == 1)
            {
                var histories = perforAgcomputeRepository.GetEntities(w => w.SecondId == request.SecondId);
                if (histories != null && histories.Any())
                    perforAgcomputeRepository.RemoveRange(histories.ToArray());

                var computes = new List<ag_compute>();
                if (second.SubmitType == 1)
                {
                    var items = perforAgfixatitemRepository.GetEntities(t => t.SecondId == request.SecondId);
                    if (items != null && items.Any())
                    {
                        var rowNumbers = items.Select(t => t.RowNumber).Where(t => t >= 0)?.Distinct();
                        if (rowNumbers != null && rowNumbers.Any())
                        {
                            foreach (var item in rowNumbers)
                            {
                                computes.Add(new ag_compute
                                {
                                    AllotId = second.AllotId,
                                    SecondId = second.Id,
                                    Department = second.Department,
                                    JobNumber = items.FirstOrDefault(t => t.RowNumber == item && t.ItemName == "人员工号")?.ItemValue,
                                    WorkPost = items.FirstOrDefault(t => t.RowNumber == item && t.ItemName == "岗位")?.ItemValue,
                                    PersonName = items.FirstOrDefault(t => t.RowNumber == item && t.ItemName == "姓名")?.ItemValue,
                                    RealGiveFee = ConvertHelper.TryDecimal(items.FirstOrDefault(t => t.RowNumber == item && t.ItemName == "实发绩效工资金额")?.ItemValue, 0),
                                });
                            }
                        }
                    }
                }
                else if (second.SubmitType == 2)
                {
                    var others = perforAgothersourceRepository.GetEntities(t => t.SecondId == request.SecondId);
                    if (others != null && others.Any())
                    {
                        foreach (var item in others)
                        {
                            computes.Add(new ag_compute
                            {
                                AllotId = second.AllotId,
                                SecondId = second.Id,
                                Department = second.Department,
                                WorkPost = item.WorkPost,
                                JobNumber = item.WorkNumber,
                                PersonName = item.Name,
                                RealGiveFee = item.RealAmount,
                            });
                        }
                    }
                }

                perforAgcomputeRepository.AddRange(computes.ToArray());
            }

            #endregion
            return result;
        }
        #endregion

        #region common
        /// <summary>
        /// 获取二次绩效
        /// </summary>
        /// <param name="secondId">二次绩效Id</param>
        /// <returns></returns>
        public ag_secondallot GetSecondallot(int secondId)
        {
            return perforAgsecondallotRepository.GetEntity(t => t.Id == secondId);
        }

        /// <summary>
        /// 获取 列
        /// </summary>
        /// <param name="tempId">模板Id</param>
        /// <param name="hospitalId">医院Id</param>
        /// <param name="department">科室</param>
        /// <param name="unitType">核算单元类型</param>
        /// <returns></returns>
        public List<HeadItem> GetHeadItems(int tempId, int hospitalId, string department, string unitType)
        {
            var tempItem = perforAgtempitemRepository.GetEntities(t => t.TempId == tempId);

            var headItems = Mapper.Map<List<HeadItem>>(tempItem) ?? new List<HeadItem>();
            //获取工作量列头
            var workItem = perforAgworkloadRepository.GetEntities(t => t.HospitalId == hospitalId && t.Department == department && t.UnitType == unitType);
            if (workItem != null && workItem.Count > 0)
            {
                var workDtos = Mapper.Map<List<HeadItem>>(workItem.Where(t => t.WorkTypeId != (int)AgWorkloadType.SingleAwards));
                workDtos.ForEach(t => { t.Type = 3; });
                headItems.AddRange(workDtos);

                workDtos = Mapper.Map<List<HeadItem>>(workItem.Where(t => t.WorkTypeId == (int)AgWorkloadType.SingleAwards));
                workDtos.ForEach(t => { t.Type = 4; });
                headItems.AddRange(workDtos);
            }
            return headItems;
        }

        /// <summary>
        /// 获取 展示数据
        /// </summary>
        /// <param name="headItems">列</param>
        /// <param name="source">数据来源 1. 二次绩效配置 2. 保存数据 </param>
        /// <param name="configs">二次绩效配置</param>
        /// <param name="fixatitems">保存数据</param>
        /// <param name="row">行号</param>
        /// <returns></returns>
        public List<BodyItem> GetBodyItems(List<HeadItem> headItems, int source, List<cof_again> configs = null, List<ag_fixatitem> fixatitems = null, int? row = null)
        {
            var bodyItems = new List<BodyItem>();
            foreach (var item in headItems)
            {
                var bodyItem = new BodyItem
                {
                    RowNumber = source == 1 ? -1 : row.Value,
                    FiledId = item.FiledId,
                    FiledName = item.FiledName,
                    FactorValue = item.FactorValue,
                    SourceType = item.SourceType,
                    Type = item.Type,
                    Sort = item.Sort,
                    Value = source == 1 ? configs.FirstOrDefault(t => t.TypeName == item.FiledName)?.Value.ToString()
                                : fixatitems.FirstOrDefault(t => t.RowNumber == row && t.ItemName == item.FiledName)?.ItemValue
                };
                bodyItems.Add(bodyItem);
            }
            return bodyItems;
        }
        #endregion

        #region 二次绩效其他来源
        public List<ag_othersource> OtherList(int secondId, int userId)
        {
            var otherSecondList = perforAgothersourceRepository.GetEntities(t => t.SecondId == secondId);
            if (otherSecondList != null && otherSecondList.Any())
            {
                return otherSecondList.OrderBy(t => t.Id).ToList();
            }
            else
            {
                var second = perforAgsecondallotRepository.GetEntity(t => t.Id == secondId);
                if (second == null) throw new PerformanceException("二次绩效信息无效！");

                var employees = personService.GetPersons(second.AllotId.Value, userId);
                if (employees == null || !employees.Any()) return new List<ag_othersource>();

                return employees.Select(t => new ag_othersource
                {
                    SecondId = secondId,
                    WorkNumber = t.PersonnelNumber,
                    Name = t.DoctorName,
                    Department = t.Department,
                    WorkPost = t.JobTitle
                }).ToList();
            }
        }

        public Dictionary<string, string> OtherListHeader(int secondId, decimal? amount)
        {
            var second = perforAgsecondallotRepository.GetEntity(t => t.Id == secondId);
            if (second == null) return new Dictionary<string, string>();

            var keyValue = new Dictionary<string, string>
            {
                {"发放月份",  $"{second.Year}年{second.Month.ToString().PadLeft(2, '0')}月"},
                {"绩效合计(考核后)",  second.RealGiveFee.ToString()},
                {"业绩分配绩效总额",  (second.RealGiveFee - (amount ?? 0)).ToString()},
            };

            return keyValue;
        }

        public List<ag_othersource> OtherSave(int secondId, List<ag_othersource> request)
        {
            var existEntities = perforAgothersourceRepository.GetEntities(t => t.SecondId == secondId);
            if (existEntities != null && existEntities.Any())
            {
                foreach (var item in request.Where(t => t.Id != 0))
                {
                    existEntities.First(t => t.Id == item.Id).WorkNumber = item.WorkNumber;
                    existEntities.First(t => t.Id == item.Id).Name = item.Name;
                    existEntities.First(t => t.Id == item.Id).Department = item.Department;
                    existEntities.First(t => t.Id == item.Id).WorkPost = item.WorkPost;
                    existEntities.First(t => t.Id == item.Id).TitlePerformance = item.TitlePerformance;
                    existEntities.First(t => t.Id == item.Id).WorkPerformance = item.WorkPerformance;
                    existEntities.First(t => t.Id == item.Id).DeptReward = item.DeptReward;
                    existEntities.First(t => t.Id == item.Id).DistPerformance = item.DistPerformance;
                    existEntities.First(t => t.Id == item.Id).OtherPerformance = item.OtherPerformance;
                    existEntities.First(t => t.Id == item.Id).NightWorkPerformance = item.NightWorkPerformance;
                    existEntities.First(t => t.Id == item.Id).RealAmount = item.RealAmount;
                }
                perforAgothersourceRepository.UpdateRange(existEntities.ToArray());

                var delIds = existEntities.Select(t => t.Id).Except(request.Select(t => t.Id));
                if (delIds != null)
                    perforAgothersourceRepository.RemoveRange(existEntities.Where(t => delIds.Contains(t.Id)).ToArray());
            }

            var addEntities = request.Where(t => t.Id == 0).ToList();
            if (addEntities != null && addEntities.Any())
            {
                addEntities.ForEach(t => t.SecondId = secondId);
                perforAgothersourceRepository.AddRange(addEntities.ToArray());
            }
            return perforAgothersourceRepository.GetEntities(t => t.SecondId == secondId);
        }
        #endregion

        #region 打印
        public List<SecPrintResponse> Print(int secondId)
        {
            var second = perforAgsecondallotRepository.GetEntity(t => t.Id == secondId);
            if (second == null) return new List<SecPrintResponse>();

            bool isOtherTemp = second.UseTempId.HasValue && second.UseTempId == 6;

            var computes = perforAgcomputeRepository.GetEntities(t => t.SecondId == secondId);
            if (computes == null || !computes.Any())
                return new List<SecPrintResponse>();


            if (isOtherTemp)
            {
                var data = perforAgothersourceRepository.GetEntities(t => t.SecondId == secondId);
                if (data == null || !data.Any()) return new List<SecPrintResponse>();

                var result = Mapper.Map<List<SecPrintResponse>>(data);
                return result.OrderBy(t => t.JobNumber).ThenBy(t => t.PersonName).ToList();
            }
            else
            {
                var itemname = new List<string> { "人员工号", "职称", "职称绩效", "工作量绩效工资", "科室单项奖励", "可分配绩效", "医院其他绩效", "夜班工作量绩效" };
                var fixaitems = perforAgfixatitemRepository.GetEntities(t => t.SecondId == secondId && itemname.Contains(t.ItemName));

                var result = new List<SecPrintResponse>();
                foreach (var item in computes)
                {
                    var sec = new SecPrintResponse
                    {
                        JobNumber = item.JobNumber,
                        PersonName = item.PersonName,
                        Department = item.Department,
                        RealAmount = item.RealGiveFee,
                    };
                    if (fixaitems != null && fixaitems.Any())
                    {
                        var rownumber = fixaitems.FirstOrDefault(t => t.ItemValue == item.JobNumber).RowNumber;
                        sec.RowNumber = rownumber ?? 0;
                        sec.WorkPost = fixaitems.FirstOrDefault(t => t.RowNumber == rownumber && t.ItemName == "职称").ItemValue;
                        sec.TitlePerfor = ConvertHelper.To<decimal>(fixaitems.FirstOrDefault(t => t.RowNumber == rownumber && t.ItemName == "职称绩效").ItemValue);
                        sec.WorkPerformance = ConvertHelper.To<decimal>(fixaitems.FirstOrDefault(t => t.RowNumber == rownumber && t.ItemName == "工作量绩效工资").ItemValue);
                        sec.DeptReward = ConvertHelper.To<decimal>(fixaitems.FirstOrDefault(t => t.RowNumber == rownumber && t.ItemName == "科室单项奖励").ItemValue);
                        sec.DistPerformance = ConvertHelper.To<decimal>(fixaitems.FirstOrDefault(t => t.RowNumber == rownumber && t.ItemName == "可分配绩效").ItemValue);
                        sec.OtherPerformance = ConvertHelper.To<decimal>(fixaitems.FirstOrDefault(t => t.RowNumber == rownumber && t.ItemName == "医院其他绩效").ItemValue);
                        sec.NightWorkPerformance = ConvertHelper.To<decimal>(fixaitems.FirstOrDefault(t => t.RowNumber == rownumber && t.ItemName == "夜班工作量绩效").ItemValue);
                    }
                    result.Add(sec);
                }
                return result.OrderBy(t => t.RowNumber).ToList();
            }
        }
        #endregion

        public List<SecondPerforResponse> DeptComputeDetail(int userId, int allotId)
        {
            var user = perforUserRepository.GetEntity(t => t.ID == userId);
            if (user == null)
                throw new NotImplementedException("人员ID无效");

            var userrole = userroleRepository.GetEntity(t => t.UserID == userId);
            var role = roleRepository.GetEntity(t => t.ID == userrole.RoleID);

            Dictionary<int, string> dict = new Dictionary<int, string>
            {
                { application.DirectorRole, AccountUnitType.科主任.ToString() },
                { application.NurseRole, AccountUnitType.护士长.ToString() },
            };

            if (!dict.Keys.Contains(role.Type.Value)) return new List<SecondPerforResponse>();

            var data = rescomputeRepository.GetEntities(t => t.AllotID == allotId && t.AccountingUnit == user.Department && t.AccountType == dict[role.Type.Value]);
            if (data == null || !data.Any()) return new List<SecondPerforResponse>();

            return Mapper.Map<List<SecondPerforResponse>>(data);
        }
    }
}
