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.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 PerforRoleRepository roleRepository;

        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,
            PerforRoleRepository roleRepository)
        {
            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.roleRepository = roleRepository;
        }

        #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();
            var secondList = perforAgsecondallotRepository.GetEntities(t => allotListId.Contains(t.AllotId.Value) && t.Department == user.Department);
            //各科室绩效分配结果
            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));

            #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;
                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.护理组);

                if (account == null) continue;

                var second = new ag_secondallot
                {
                    AllotId = item,
                    Year = allot.Year,
                    Month = allot.Month,
                    Department = user.Department,
                    UnitType = ((UnitType)account.UnitType).ToString(),
                    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)
        {
            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();

            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(GetBringItems(request, headItems));   //更换模板时，会自动保存顶部数据
                }
                else
                {
                    //无数据 根据IsBring带出历史二次绩效中需要带出的数据
                    result.BodyItems = GetBringItems(request, headItems);
                    result.BodyItems.AddRange(Mapper.Map<List<BodyItem>>(headItems.Where(t => t.Type == 1)));
                }
            }

            //检验 二次绩效配置 数据是否 有值，无则补充带出
            FillData(second, result.BodyItems);
            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>
        /// <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 = headItems.FirstOrDefault(h => h.FiledName == t.ItemName && h.Type == t.Type)?.FiledId ?? $"{t.ItemName}{t.Type}",
                    FiledName = t.ItemName,
                    SourceType = t.SourceType ?? 0,
                    Type = t.Type ?? 0,
                    Value = t.ItemValue,
                    Sort = t.Sort ?? 0
                }).ToList();
            }
            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 keyValue = new Dictionary<string, string>
            {
                {"发放月份",  $"{second.Year}年{second.Month.ToString().PadLeft(2, '0')}月"},
                {"绩效合计(考核后)",  second.RealGiveFee.ToString()},
            };
            var config = perforCofagainRepository.GetEntities(t => t.AllotID == second.AllotId);
            if (config != null && config.Any())
                config.ForEach(t =>
                {
                    keyValue.Add(t.TypeName, t.Value.ToString());
                });

            foreach (var item in keyValue)
            {
                var header = bodyItems.FirstOrDefault(t => t.FiledName == item.Key);
                if (header != null && string.IsNullOrEmpty(header.Value))
                    bodyItems.FirstOrDefault(t => t.FiledName == item.Key).Value = item.Value;
            }
        }
        #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);
            foreach (var item in request)
            {
                if (fixatitems != null && fixatitems.Any(t => t.SecondId == secondId && t.RowNumber == item.RowNumber && t.ItemName == item.ItemName))
                {
                    var cellItem = fixatitems.First(t => t.SecondId == secondId && t.RowNumber == item.RowNumber && t.ItemName == item.ItemName);
                    cellItem.ItemValue = item.ItemValue;
                    cellItem.Sort = item.Sort;
                    cellItem.SourceType = item.SourceType;
                    cellItem.Type = item.Type;
                    cellItem.UnitType = item.UnitType;
                    perforAgfixatitemRepository.Update(cellItem);
                }
                else
                {
                    perforAgfixatitemRepository.Add(item);
                }
            }
            return DelValue(second.Id, request);
        }

        /// <summary>
        /// 删除未保存的历史数据
        /// </summary>
        /// <param name="secondId"></param>
        /// <param name="fixatitems"></param>
        /// <returns></returns>
        public bool DelValue(int secondId, List<ag_fixatitem> fixatitems)
        {
            if (secondId == 0)
                throw new PerformanceException("二次绩效Id无效");

            var fixatlist = perforAgfixatitemRepository.GetEntities(t => t.SecondId == secondId);
            if (fixatitems == null || fixatitems.Count == 0)
            {
                return perforAgfixatitemRepository.RemoveRange(fixatlist.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)
                return perforAgfixatitemRepository.RemoveRange(fixatlist.Where(t => delRows.Contains(t.RowNumber)).ToArray());

            return true;
        }

        /// <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)
        {
            var temps = perforAgtempRepository.GetEntities();
            if (temps != null && temps.Any())
            {
                var useTemp = perforAgusetempRepository.GetEntity(t => t.HospitalId == hospitalid && t.Department == department);
                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);
        }

        /// <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,
            };
            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}";

            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);
        }

        #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 submittype)
        {
            second.Status = 2;
            second.SubmitType = submittype;
            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("该绩效未提交至审核，请确认");

            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,
                                    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 = item.Department,
                                WorkPost = item.WorkPost,
                                JobNumber = item.WorkNumber,
                                PersonName = item.Name,
                                RealGiveFee = item.Amount,
                            });
                        }
                    }
                }

                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);
                workDtos.ForEach(t => { t.Type = 3; });
                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)
        {
            var otherSecondList = perforAgothersourceRepository.GetEntities(t => t.SecondId == secondId);
            return otherSecondList?.OrderBy(t => t.Id).ToList();
        }

        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).Amount = item.Amount;
                }
                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
    }
}
