using AutoMapper;
using NPOI.SS.Formula.Functions;
using Performance.DtoModels;
using Performance.EntityModels;
using Performance.Infrastructure;
using Performance.Repository;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Text.RegularExpressions;

namespace Performance.Services
{
    public class ComputeService : IAutoInjection
    {
        private readonly PerforResaccountRepository perforResaccountRepository;
        //private readonly PerforResaccountnurseRepository _perforResAccountnurseRepository;
        private readonly PerforPersheetRepository _perforPerSheetRepository;
        private readonly PerforImdataRepository _perforImDataRepository;
        private readonly PerforImheaderRepository _perforImheaderRepository;
        private readonly PerforRescomputeRepository _perforRescomputeRepository;
        private readonly PerforResspecialunitRepository _perforResspecialunitRepository;
        private readonly PerforPeragainallotRepository _perforPeragainallotRepository;
        private readonly PerforUserRepository _perforUserRepository;
        private readonly PerforAgemployeeRepository _perforAgemployeeRepository;
        private readonly PerforResbaiscnormRepository perforResbaiscnormRepository;
        private readonly PerforCofincomeRepository _perforCofincomeRepository;
        private readonly PerforAgsecondallotRepository _perforAgsecondallotRepository;
        private readonly PerforAgcomputeRepository _perforAgcomputeRepository;
        private readonly PerforImemployeeclinicRepository _perforImemployeeclinicRepository;
        private readonly PerforImemployeeRepository _perforImemployeeRepository;
        private readonly PerforPerallotRepository perforPerallotRepository;
        private readonly PerforHospitalRepository hospitalRepository;

        public ComputeService(PerforResaccountRepository perforResaccountRepository,
            //PerforResaccountnurseRepository perforResAccountnurseRepository,
            PerforPersheetRepository perforPerSheetRepository,
            PerforImdataRepository perforImDataRepository,
            PerforImheaderRepository perforImheaderRepository,
            PerforRescomputeRepository perforRescomputeRepository,
            PerforResspecialunitRepository perforResspecialunitRepository,
            PerforPeragainallotRepository perforPeragainallotRepository,
            PerforUserRepository perforUserRepository,
            PerforAgemployeeRepository perforAgemployeeRepository,
            PerforResbaiscnormRepository perforResbaiscnormRepository,
            PerforCofincomeRepository perforCofincomeRepository,
            PerforAgsecondallotRepository perforAgsecondallotRepository,
            PerforAgcomputeRepository perforAgcomputeRepository,
            PerforImemployeeclinicRepository perforImemployeeclinicRepository,
            PerforImemployeeRepository perforImemployeeRepository,
            PerforPerallotRepository perforPerallotRepository,
            PerforHospitalRepository hospitalRepository)
        {
            this.perforResaccountRepository = perforResaccountRepository;
            //this._perforResAccountnurseRepository = perforResAccountnurseRepository;
            this._perforPerSheetRepository = perforPerSheetRepository;
            this._perforImDataRepository = perforImDataRepository;
            this._perforImheaderRepository = perforImheaderRepository;
            this._perforRescomputeRepository = perforRescomputeRepository;
            this._perforResspecialunitRepository = perforResspecialunitRepository;
            this._perforPeragainallotRepository = perforPeragainallotRepository;
            this._perforUserRepository = perforUserRepository;
            this._perforAgemployeeRepository = perforAgemployeeRepository;
            this.perforResbaiscnormRepository = perforResbaiscnormRepository;
            this._perforCofincomeRepository = perforCofincomeRepository;
            this._perforAgsecondallotRepository = perforAgsecondallotRepository;
            this._perforAgcomputeRepository = perforAgcomputeRepository;
            this._perforImemployeeclinicRepository = perforImemployeeclinicRepository;
            this._perforImemployeeRepository = perforImemployeeRepository;
            this.perforPerallotRepository = perforPerallotRepository;
            this.hospitalRepository = hospitalRepository;
        }

        public int IsShowManage(int allotId)
        {
            var allot = perforPerallotRepository.GetEntity(t => t.ID == allotId);
            if (allot == null)
                throw new PerformanceException("绩效信息无效");

            return hospitalRepository.GetEntity(t => t.ID == allot.HospitalId)?.IsShowManage ?? 1;
        }

        /// <summary>
        /// 返回绩效发放列表
        /// </summary>
        /// <param name="allotId">绩效ID</param>
        /// <param name="type">绩效基数核算参考对象</param>
        /// <returns></returns>
        public List<ResComputeResponse> GetCompute(int allotId, int type)
        {
            var data = new List<ResComputeResponse>();

            var items = EnumHelper.GetItems<AccountUnitType>();
            if (!items.Any(t => t.Value == type))
                throw new PerformanceException("参数错误，type无效");

            Dictionary<int, List<string>> pairs = new Dictionary<int, List<string>>
            {
                { (int)AccountUnitType.科主任, new List<string>{ UnitType.医生组.ToString(), UnitType.医技组.ToString() } },
                { (int)AccountUnitType.护士长, new List<string>{ UnitType.护理组.ToString() } },
                { (int)AccountUnitType.Null, new List<string>
                    {
                        UnitType.特殊核算组.ToString(),
                        UnitType.其他医生组.ToString(),
                        UnitType.其他护理组.ToString(),
                        UnitType.其他医技组.ToString()
                    }
                },
            };
            var isShowManage = IsShowManage(allotId);

            if (pairs.Keys.Any(t => t == type))
            {
                var employees = _perforImemployeeclinicRepository.GetEntities(t => t.AllotID == allotId && pairs[type].Contains(t.UnitType));
                if (employees == null || !employees.Any()) return new List<ResComputeResponse>();

                var computes = _perforRescomputeRepository.GetEntities(t => t.AllotID == allotId);
                if (computes == null || !computes.Any()) return new List<ResComputeResponse>();

                var joinData = employees.Join(computes, outer => new { outer.AccountingUnit, EmployeeName = outer.DoctorName },
                    inner => new { inner.AccountingUnit, inner.EmployeeName }, (outer, inner) => inner).ToList();
                if (joinData == null || !joinData.Any()) return new List<ResComputeResponse>();

                if (type != (int)AccountUnitType.Null)
                {
                    var accountUnit = computes.Where(t => t.AccountType == ((AccountUnitType)type).ToString() && joinData.Select(join => join.EmployeeName).Contains(t.EmployeeName));

                    if (accountUnit != null && accountUnit.Any())
                    {
                        accountUnit.ToList().ForEach(t =>
                        {
                            var compute = joinData.First(join => join.EmployeeName == t.EmployeeName);
                            if (compute.AccountingUnit != t.AccountingUnit)
                                joinData.Add(t);
                        });
                    }
                }
                else
                {
                    var accountUnit = computes.Where(t => joinData.Select(join => join.EmployeeName).Contains(t.EmployeeName));
                    if (accountUnit != null && accountUnit.Any())
                    {
                        var delData = new List<res_compute>();
                        foreach (var item in joinData)
                        {
                            accountUnit.Where(join => join.EmployeeName == item.EmployeeName).ToList().ForEach(t =>
                            {
                                if (item.AccountType == t.AccountType && item.AccountingUnit != t.AccountingUnit)
                                    delData.Add(item);
                            });
                        }
                        if (delData.Count > 0)
                            joinData.RemoveAll(t => delData.Select(d => d.ID).Contains(t.ID));
                    }
                }
                data = Mapper.Map<List<ResComputeResponse>>(joinData);
                data?.ForEach(t =>
                {
                    t.WorkTime = string.IsNullOrEmpty(t.WorkTime) ? null : Convert.ToDateTime(t.WorkTime).ToString("yyyy-MM-dd");
                    if (isShowManage == 2)
                    {
                        t.PerforSumFee = t.ShouldGiveFee;
                        var employee = employees.FirstOrDefault(e => e.DoctorName == t.EmployeeName && e.AccountingUnit == t.AccountingUnit);
                        var scoreAverageRate = t.ScoreAverageRate ?? employee.ScoreAverageRate ?? 0;
                        var attendance = t.Attendance ?? employee.Attendance ?? 0;
                        t.GiveFee = t.ShouldGiveFee * scoreAverageRate * attendance + t.OtherPerfor;
                        t.RealGiveFee = t.GiveFee * (t.Adjust ?? 1m);
                        t.BaiscNormValue = t.RealGiveFee;
                    }
                });
                return data?.OrderByDescending(t => t.AccountingUnit).ToList();
            }
            else
            {
                var compute = _perforRescomputeRepository.GetEntities(t => t.AllotID == allotId && t.AccountType == items.FirstOrDefault(p => p.Value == type).Name)
                     ?.OrderByDescending(t => t.RealGiveFee).ThenBy(t => t.FitPeople).ThenBy(t => t.AccountingUnit).ToList();
                data = Mapper.Map<List<ResComputeResponse>>(compute);
                data?.ForEach(t => t.WorkTime = string.IsNullOrEmpty(t.WorkTime) ? null : Convert.ToDateTime(t.WorkTime).ToString("yyyy-MM-dd"));
                return data?.OrderByDescending(t => t.AccountingUnit).ToList();
            }
        }

        /// <summary>
        /// 返回特殊科室发放列表
        /// </summary>
        /// <param name="allotId">绩效ID</param>
        /// <returns></returns>
        public List<res_specialunit> GetSpecial(int allotId)
        {
            var list = _perforResspecialunitRepository.GetEntities(t => t.AllotID == allotId);
            if (list != null && list.Any())
            {
                list = list.OrderByDescending(t => t.AccountingUnit).ThenBy(t => t.RealGiveFee).ToList();
                return Mapper.Map<List<res_specialunit>>(list);
            }
            return new List<res_specialunit>();
        }

        /// <summary>
        /// 返回医生组科室绩效
        /// </summary>
        /// <param name="allotId">绩效ID</param>
        /// <returns></returns>
        public List<DeptResponse> GetDoctorPerformance(int allotId)
        {
            List<int> types = new List<int> { (int)UnitType.医生组, (int)UnitType.医技组 };
            var list = perforResaccountRepository.GetEntities(t => types.Contains(t.UnitType.Value) && t.AllotID == allotId)?.OrderBy(t => t.UnitType).ThenByDescending(t => t.AccountingUnit);
            List<DeptResponse> doctor = Mapper.Map<List<DeptResponse>>(list);
            doctor?.ForEach(t => t.UnitName = ((UnitType)t.UnitType).ToString());
            return doctor;
        }

        /// <summary>
        /// 返回护理组科室绩效
        /// </summary>
        /// <param name="allotId">绩效ID</param>
        /// <returns></returns>
        public List<DeptResponse> GetNursePerformance(int allotId)
        {
            var list = perforResaccountRepository.GetEntities(t => t.UnitType == (int)UnitType.护理组 && t.AllotID == allotId)?.OrderBy(t => t.UnitType).ThenByDescending(t => t.AccountingUnit);
            List<DeptResponse> nurse = Mapper.Map<List<DeptResponse>>(list);
            nurse?.ForEach(t => t.UnitName = ((UnitType)t.UnitType).ToString());
            return nurse;
        }

        /// <summary>
        /// 返回其他组科室绩效
        /// </summary>
        /// <param name="allotId">绩效ID</param>
        /// <returns></returns>
        public List<DeptResponse> GetOtherPerformance(int allotId)
        {
            var unitType = new List<int> { (int)UnitType.其他医技组, (int)UnitType.其他医生组, (int)UnitType.其他护理组, (int)UnitType.专家组 };
            var list = perforResaccountRepository.GetEntities(t => unitType.Contains(t.UnitType.Value) && t.AllotID == allotId)?.OrderBy(t => t.UnitType).ThenByDescending(t => t.AccountingUnit);
            List<DeptResponse> other = Mapper.Map<List<DeptResponse>>(list);
            other?.ForEach(t => t.UnitName = ((UnitType)t.UnitType).ToString());
            return other;
        }

        /// <summary>
        /// 返回院领导、中层、工勤组绩效
        /// </summary>
        /// <param name="allotId">绩效ID</param>
        /// <returns></returns>
        public List<DeptResponse> GetAdminPerformance(int allotId)
        {
            var result = new List<DeptResponse>();

            var resData = perforResaccountRepository.GetEntities(t => t.AllotID == allotId);
            if (resData != null && resData.Any())
            {
                result.AddRange(Mapper.Map<List<DeptResponse>>(resData));
                result.ForEach(t =>
                {
                    t.UnitName = ((UnitType)t.UnitType).ToString();
                    t.ScoringPerfor = t.PerforFee * (t.ScoringAverage ?? 0);
                });
                result = result.OrderBy(t => t.UnitType).ThenBy(t => t.AccountingUnit).ToList();
            }

            var accountType = new List<AccountUnitType> { AccountUnitType.行政高层, AccountUnitType.行政中层, AccountUnitType.行政工勤 };
            var list = _perforRescomputeRepository.GetEntities(t => t.AllotID == allotId && accountType.Select(a => a.ToString()).Contains(t.AccountType));
            if (list == null || !list.Any()) return result;

            List<DeptResponse> adminPerfor = list.GroupBy(t => new { t.AccountingUnit, t.AccountType })
                .Select(t => new DeptResponse
                {
                    UnitName = t.Key.AccountType,
                    AccountingUnit = t.Key.AccountingUnit,
                    Department = t.Key.AccountingUnit,
                    Number = t.Count(),
                    //Extra = t.FirstOrDefault(group => group.Punishment > 0)?.Punishment, // 医院奖罚
                    //ScoringAverage = t.FirstOrDefault(group => group.ScoreAverageRate > 0)?.ScoreAverageRate, //考核得分率
                    //AdjustFactor = t.FirstOrDefault(group => group.Adjust > 0)?.Adjust, //调节系数
                    //WorkloadFee = t.Sum(group => group.Workload),  //工作量绩效
                    //PerforTotal = t.Sum(group => group.RealGiveFee),  //绩效合计
                    //ScoringPerfor = t.Sum(group => group.RealGiveFee) * (t.FirstOrDefault(group => group.ScoreAverageRate > 0)?.ScoreAverageRate ?? 0),
                    Avg = t.Sum(group => group.RealGiveFee) / t.Count(), //人均绩效
                    OtherPerfor1 = t.Sum(group => group.OtherPerfor),
                    RealGiveFee = t.Sum(group => group.RealGiveFee) + t.Sum(group => group.OtherPerfor),  //实发绩效
                }).ToList();
            var enumItems = EnumHelper.GetItems<AccountUnitType>();
            adminPerfor = adminPerfor.OrderBy(t => enumItems.FirstOrDefault(e => e.Name == t.UnitName).Value).ThenBy(t => t.AccountingUnit).ToList();
            result.AddRange(adminPerfor);

            return result;
        }

        /// <summary>
        /// 查看科室绩效
        /// </summary>
        /// <param name="allotId"></param>
        /// <param name="department"></param>
        /// <param name="type"></param>
        /// <returns></returns>
        public DeptDetailResponse GetDepartmentDetail(int allotId, string department, int type)
        {
            if (type == 1)
            {
                var accountList = perforResaccountRepository.GetEntities(t => t.UnitType != (int)UnitType.护理组 && t.AllotID == allotId && t.AccountingUnit == department);
                if (accountList != null)
                    return GetDepartmentDetail(allotId, accountList.First().ID, type);
            }
            else if (type == 2)
            {
                var accountList = perforResaccountRepository.GetEntities(t => t.UnitType == (int)UnitType.护理组 && t.AllotID == allotId && t.AccountingUnit == department);
                if (accountList != null)
                    return GetDepartmentDetail(allotId, accountList.First().ID, type);
            }
            return null;
        }


        /// <summary>
        /// 返回科室详情
        /// </summary>
        /// <param name="allotId"></param>
        /// <param name="accountId"></param>
        /// <param name="type"> 1 医生组 2 护理组</param>
        /// <returns></returns>
        public DeptDetailResponse GetDepartmentDetail(int allotId, int accountId, int type)
        {
            var sheetList = _perforPerSheetRepository.GetEntities(t => t.AllotID == allotId);
            if (type == 1)
            {
                var doctor = perforResaccountRepository.GetEntity(t => t.UnitType != (int)UnitType.护理组 && t.AllotID == allotId && t.ID == accountId);

                DeptDetailResponse response = new DeptDetailResponse()
                {
                    Pandect = Mapper.Map<PerDataAccountBaisc>(doctor),
                    Economic = new List<DeptDetail>(),
                    Workload = new List<DeptDetail>()
                };

                var sheetWorkload = sheetList.FirstOrDefault(t => t.SheetType == (int)SheetType.ComputeDoctorWorkload);
                if (sheetWorkload == null)
                    return null;
                var dataWorkloadList = _perforImDataRepository.GetEntities(t => t.SheetID == sheetWorkload.ID && t.IsTotal != 1 && t.AccountingUnit == doctor.AccountingUnit);
                if (dataWorkloadList != null && dataWorkloadList.Count > 0)
                    dataWorkloadList.ForEach(t => response.Workload.Add(new DeptDetail { ItemName = t.TypeName, ItemValue = t.CellValue ?? 0 }));

                var sheetEconomic = sheetList.FirstOrDefault(t => t.SheetType == (int)SheetType.ComputeEconomic);
                if (sheetEconomic == null)
                    return null;
                var dataEconomicList = _perforImDataRepository.GetEntities(t => t.SheetID == sheetEconomic.ID && t.UnitType == 1 && t.IsTotal != 1 && t.AccountingUnit == doctor.AccountingUnit);
                if (dataEconomicList != null && dataEconomicList.Count > 0)
                    dataEconomicList.ForEach(t => response.Economic.Add(new DeptDetail { ItemName = t.TypeName, ItemValue = t.CellValue ?? 0 }));

                return response;
            }
            else if (type == 2)
            {
                var nurse = perforResaccountRepository.GetEntity(t => t.UnitType == (int)UnitType.护理组 && t.AllotID == allotId && t.ID == accountId);
                DeptDetailResponse response = new DeptDetailResponse()
                {
                    Pandect = Mapper.Map<PerDataAccountBaisc>(nurse),
                    Economic = new List<DeptDetail>(),
                    Workload = new List<DeptDetail>()
                };

                var sheetWorkload = sheetList.FirstOrDefault(t => t.SheetType == (int)SheetType.ComputeNurseWorkload);
                if (sheetWorkload == null)
                    return null;
                var dataWorkloadList = _perforImDataRepository.GetEntities(t => t.SheetID == sheetWorkload.ID && t.IsTotal != 1 && t.AccountingUnit == nurse.AccountingUnit);
                if (dataWorkloadList != null && dataWorkloadList.Count > 0)
                    dataWorkloadList.ForEach(t => response.Workload.Add(new DeptDetail { ItemName = t.TypeName, ItemValue = t.CellValue ?? 0 }));

                var sheetEconomic = sheetList.FirstOrDefault(t => t.SheetType == (int)SheetType.ComputeEconomic);
                if (sheetEconomic == null)
                    return null;
                var dataEconomicList = _perforImDataRepository.GetEntities(t => t.SheetID == sheetEconomic.ID && t.UnitType == 2 && t.IsTotal != 1 && t.AccountingUnit == nurse.AccountingUnit);
                if (dataEconomicList != null && dataEconomicList.Count > 0)
                    dataEconomicList.ForEach(t => response.Economic.Add(new DeptDetail { ItemName = t.TypeName, ItemValue = t.CellValue ?? 0 }));
                return response;
            }

            return null;
        }

        /// <summary>
        /// 返回绩效发放列表
        /// </summary>
        /// <param name="allotId">绩效ID</param>
        /// <returns></returns>
        public List<ComputeResponse> AllCompute(int allotId)
        {
            var list = new List<ComputeResponse>();
            var allot = _perforRescomputeRepository.GetEntities(t => t.AllotID == allotId)?.OrderByDescending(t => t.AccountingUnit);
            list = Mapper.Map<List<ComputeResponse>>(allot);
            list?.ForEach(t => t.Source = "一次绩效");
            var again = _perforAgcomputeRepository.GetEntities(t => t.AllotId == allotId);
            if (again != null && again.Any())
            {
                var group = again.GroupBy(t => new { t.Department, t.WorkPost, t.JobNumber, t.PersonName })
                    .Select(t => new
                    {
                        department = t.Key.Department,
                        jobtitle = t.Key.WorkPost,
                        jobnumber = t.Key.JobNumber,
                        name = t.Key.PersonName,
                        fee = t.Sum(g => g.RealGiveFee)
                    });
                list.AddRange(group.Select(t => new ComputeResponse
                {
                    Source = "二次绩效",
                    AccountingUnit = t.department,
                    JobNumber = t.jobnumber,
                    JobTitle = t.jobtitle,
                    EmployeeName = t.name,
                    RealGiveFee = t.fee
                }).OrderByDescending(t => t.AccountingUnit));
            }
            return list;
        }

        /// <summary>
        /// 返回绩效发放列表
        /// 科主任护士长返回管理绩效
        /// </summary>
        /// <param name="allotId">绩效ID</param>
        /// <returns></returns>
        public List<ComputeResponse> AllManageCompute(int allotId)
        {
            var list = new List<ComputeResponse>();
            var allot = _perforRescomputeRepository.GetEntities(t => t.AllotID == allotId)?.OrderByDescending(t => t.AccountingUnit);
            if (allot != null && allot.Any(t => t.AllotID == allotId))
            {
                var types = new List<string> { AccountUnitType.护士长.ToString(), AccountUnitType.科主任.ToString() };
                list = allot.Select(t => new ComputeResponse
                {
                    Source = "一次绩效",
                    AccountingUnit = t.AccountingUnit,
                    EmployeeName = t.EmployeeName,
                    JobNumber = t.JobNumber,
                    JobTitle = t.JobTitle,
                    RealGiveFee = types.Contains(t.AccountType) ? t.ShouldGiveFee : t.RealGiveFee
                }).ToList();
            }
            var again = _perforAgcomputeRepository.GetEntities(t => t.AllotId == allotId);
            if (again != null && again.Any())
            {
                var group = again.GroupBy(t => new { t.Department, t.WorkPost, t.JobNumber, t.PersonName })
                    .Select(t => new
                    {
                        department = t.Key.Department,
                        jobtitle = t.Key.WorkPost,
                        jobnumber = t.Key.JobNumber,
                        name = t.Key.PersonName,
                        fee = t.Sum(g => g.RealGiveFee)
                    });
                list.AddRange(group.Select(t => new ComputeResponse
                {
                    Source = "二次绩效",
                    AccountingUnit = t.department,
                    JobNumber = t.jobnumber,
                    JobTitle = t.jobtitle,
                    EmployeeName = t.name,
                    RealGiveFee = t.fee
                }).OrderByDescending(t => t.AccountingUnit));
            }
            return list;
        }

        public res_compute GetComputeSingle(int computeid)
        {
            return _perforRescomputeRepository.GetEntity(t => t.ID == computeid);
        }

        /// <summary>
        /// 修改实发绩效
        /// </summary>
        /// <param name="type"></param>
        /// <param name="id"></param>
        /// <param name="score"></param>
        /// <returns></returns>
        public res_compute UpdateRealfee(ComputerRequest request, int userId, string realName)
        {
            var compute = _perforRescomputeRepository.GetEntity(t => t.ID == request.ComputeId);
            var log = JsonHelper.Deserialize<List<ChangeLog>>(compute.ChangeLog);
            log = log ?? new List<ChangeLog>();
            log.Add(new ChangeLog
            {
                uid = userId,
                user = realName,
                date = DateTime.Now,
                value = compute.RealGiveFee
            });
            compute.RealGiveFee = request.RealGiveFee;
            compute.ChangeLog = JsonHelper.Serialize(log);
            if (!_perforRescomputeRepository.Update(compute))
                throw new PerformanceException("修改失败");

            return compute;
        }

        /// <summary>
        /// 返回绩效平均值
        /// </summary>
        /// <param name="type"></param>
        /// <param name="id"></param>
        /// <param name="score"></param>
        /// <returns></returns>
        public List<res_baiscnorm> GetBaiscnorm(int allotId)
        {
            return perforResbaiscnormRepository.GetEntities(t => t.AllotID == allotId).OrderBy(t => t.PositionName).ToList();
        }

        /// <summary>
        /// 返回科室详情
        /// </summary>
        /// <param name="allotId"></param>
        /// <param name="accountId"></param>
        /// <param name="type"></param>
        /// <returns></returns>
        public DeptDataDetails DeptDetail(int accountId)
        {
            var sheetType = new List<int> { (int)SheetType.Income, (int)SheetType.OtherIncome, (int)SheetType.Expend, (int)SheetType.Workload };
            var doctor = perforResaccountRepository.GetEntity(t => t.ID == accountId);
            string typeValue = EnumHelper.GetItems<UnitType>().FirstOrDefault(t => t.Value == doctor.UnitType).Name.ToString();
            var allot = perforPerallotRepository.GetEntity(t => t.ID == doctor.AllotID);
            DeptDataDetails deptDetails = new DeptDataDetails
            {
                ShowFormula = allot.ShowFormula,
                Pandect = Mapper.Map<PerDataAccountBaisc>(doctor),
                Detail = new List<DetailDtos>()
            };
            int type = doctor.UnitType.Value;
            if (type == (int)UnitType.专家组 || type == (int)UnitType.其他医技组 || type == (int)UnitType.其他医生组)
                type = 1;
            else if (type == (int)UnitType.其他护理组)
                type = 2;
            var basicData = _perforImDataRepository.GetEntities(t => t.AllotID == doctor.AllotID && t.UnitType == type && t.AccountingUnit == doctor.AccountingUnit);
            var persheet = _perforPerSheetRepository.GetEntities(t => t.AllotID == doctor.AllotID);

            //科室经济
            var sheetEconomic = persheet.FirstOrDefault(t => t.SheetType == (int)SheetType.ComputeEconomic);
            var dataEconomicList = basicData.Where(t => t.SheetID == sheetEconomic?.ID && t.UnitType == type && t.IsTotal != 1 && t.AccountingUnit == doctor.AccountingUnit).ToList();
            var economic = dataEconomicList?.Select(t => new DeptDetail { ItemName = t.TypeName.Replace($"({typeValue})", ""), ItemValue = t.CellValue ?? 0 });

            var headers = _perforImheaderRepository.GetEntities(t => t.AllotID == doctor.AllotID);
            Regex reg = new Regex("[0-9]*");
            foreach (var stype in sheetType)
            {
                foreach (var sheet in persheet.Where(t => t.SheetType == stype))
                {
                    var sheetName = reg.Replace(sheet.SheetName, "", 5).Replace(".", "").Replace(" ", "");
                    var sheetData = basicData.Where(t => t.SheetID == sheet.ID).ToList();
                    if (sheetData == null || !sheetData.Any()) continue;

                    var headerData = headers?.Where(t => t.SheetID == sheet.ID);

                    var item = new DetailDtos
                    {
                        ItemName = sheetName,
                        IncomeType = sheet.SheetType == (int)SheetType.Expend ? 2 : sheet.SheetType == (int)SheetType.Workload ? 3 : 1,
                        Amount = (sheet.SheetType == (int)SheetType.Workload ? doctor.WorkloadFee : economic.FirstOrDefault(t => t.ItemName.Contains(sheetName))?.ItemValue) ?? 0m,
                    };

                    var items = sheetData?.Select(t => new DetailModule
                    {
                        ItemName = t.TypeName,
                        CellValue = t.CellValue,
                        Factor = sheet.SheetType == (int)SheetType.Workload ? t.FactorValue : t.FactorValue * 100,
                        ItemValue = t.IsFactor == 1 ? (t.CellValue * (t.FactorValue ?? 0)) : t.CellValue
                    }).ToList();

                    if (items != null && items.Any())
                    {
                        items = items.GroupBy(t => t.ItemName).Select(t => new DetailModule
                        {
                            ItemName = t.Key,
                            CellValue = t.Sum(group => group.CellValue),
                            Factor = t.FirstOrDefault().Factor,
                            ItemValue = t.Sum(group => group.ItemValue),
                        }).ToList();
                    }

                    if (headerData != null && headerData.Any())
                    {
                        items = items
                            ?.OrderBy(t => (headerData.FirstOrDefault(h => h.CellValue == t.ItemName)?.PointCell) ?? 100)
                            ?.ThenBy(t => t.ItemName).ToList();
                    }

                    item.Items = items;
                    deptDetails.Detail.Add(item);
                }
            }
            return deptDetails;
        }


        public int GetAccountId(int secondId)
        {
            var second = _perforAgsecondallotRepository.GetEntity(t => t.Id == secondId);
            if (second != null)
            {
                var unitType = EnumHelper.GetItems<UnitType>().FirstOrDefault(t => t.Name == second.UnitType);
                var account = perforResaccountRepository.GetEntity(t => t.AllotID == second.AllotId && t.UnitType == unitType.Value && t.Department == second.Department);
                return account?.ID ?? 0;
            }
            return 0;
        }
    }
}
