using Microsoft.EntityFrameworkCore.Metadata.Internal;
using Microsoft.Extensions.Logging;
using Performance.DtoModels;
using Performance.EntityModels;
using Performance.Infrastructure;
using Performance.Repository;
using Performance.Services.ExtractExcelService;
using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Linq;
using System.Linq.Expressions;
using System.Text;
using System.Text.RegularExpressions;

namespace Performance.Services
{
    public class ExConfigService : IAutoInjection
    {
        private readonly PerforExtypeRepository extypeRepository;
        private readonly PerforExscriptRepository exscriptRepository;
        private readonly PerforExmoduleRepository exmoduleRepository;
        private readonly PerforExitemRepository exitemRepository;
        private readonly PerforExspecialRepository exspecialRepository;
        private readonly PerforPerallotRepository perallotRepository;
        private readonly PerforPersheetRepository persheetRepository;
        private readonly PerforImdataRepository imdataRepository;
        private readonly PerforHospitalconfigRepository hospitalconfigRepository;
        private readonly PerforHospitalRepository hospitalRepository;
        private readonly PerforExtractRepository extractRepository;
        private readonly PerforModdicRepository moddicRepository;
        private readonly QueryService queryService;
        private readonly ILogger logger;

        public ExConfigService(PerforExtypeRepository extypeRepository,
            PerforExscriptRepository exscriptRepository,
            PerforExmoduleRepository exmoduleRepository,
            PerforExitemRepository exitemRepository,
            PerforExspecialRepository exspecialRepository,
            PerforPerallotRepository perallotRepository,
            PerforPersheetRepository persheetRepository,
            PerforImdataRepository imdataRepository,
            PerforHospitalconfigRepository hospitalconfigRepository,
            PerforHospitalRepository hospitalRepository,
            PerforExtractRepository extractRepository,
            PerforModdicRepository moddicRepository,
            QueryService queryService,
            ILogger<ExConfigService> logger
            )
        {
            this.extypeRepository = extypeRepository;
            this.exscriptRepository = exscriptRepository;
            this.exmoduleRepository = exmoduleRepository;
            this.exitemRepository = exitemRepository;
            this.exspecialRepository = exspecialRepository;
            this.perallotRepository = perallotRepository;
            this.persheetRepository = persheetRepository;
            this.imdataRepository = imdataRepository;
            this.hospitalconfigRepository = hospitalconfigRepository;
            this.hospitalRepository = hospitalRepository;
            this.extractRepository = extractRepository;
            this.moddicRepository = moddicRepository;
            this.queryService = queryService;
            this.logger = logger;
        }

        #region Modules

        public List<ex_module> QueryModule(int hospitalId)
        {
            //首次添加费用字典默认值
            DefaultModules(hospitalId);

            var list = exmoduleRepository.GetEntities(t => t.HospitalId == hospitalId).OrderBy(t => t.ModuleName).ToList();
            return list;
        }

        private void DefaultModules(int hospitalId)
        {
            var moduleList = new ex_module[]
            {
                new ex_module{ ModuleName = "1.0.1 额外收入", SheetType = (int)SheetType.OtherIncome },
                new ex_module{ ModuleName = "1.1.1 门诊开单收入", SheetType = (int)SheetType.Income },
                new ex_module{ ModuleName = "1.1.2 门诊执行收入", SheetType = (int)SheetType.Income },
                new ex_module{ ModuleName = "1.2.1 住院开单收入", SheetType = (int)SheetType.Income },
                new ex_module{ ModuleName = "1.2.2 住院执行收入", SheetType = (int)SheetType.Income },
                new ex_module{ ModuleName = "2.1 成本支出统计表", SheetType = (int)SheetType.Expend },
                new ex_module{ ModuleName = "3.1 医生组工作量绩效测算表", SheetType = (int)SheetType.Workload },
                new ex_module{ ModuleName = "3.2 护理组工作量绩效测算表", SheetType = (int)SheetType.Workload },
            };

            var data = exmoduleRepository.GetEntities(t => t.HospitalId == hospitalId);
            var inexistence = data == null ? moduleList : moduleList.Where(t => !data.Select(p => p.ModuleName).ToArray().Contains(t.ModuleName));

            if (inexistence != null && inexistence.Any())
            {
                List<ex_module> modules = new List<ex_module>();
                foreach (var item in inexistence)
                {
                    var module = new ex_module
                    {
                        HospitalId = hospitalId,
                        ModuleName = item.ModuleName,
                        SheetType = (int)item.SheetType,
                        ReadOnly = 1,
                        TypeId = null,
                    };
                    modules.Add(module);
                }
                if (modules.Any())
                    exmoduleRepository.AddRange(modules.ToArray());
            }
        }

        public ex_module AddModule(ModModuleRequest request)
        {
            if (!new int[] { (int)SheetType.Income, (int)SheetType.OtherWorkload, (int)SheetType.Assess }.Contains(request.SheetType.Value))
                throw new PerformanceException("模块类型错误，只支持收入模板配置");

            string addname = "";
            if (request.SheetType == (int)SheetType.Income)
            {
                string[] array = new string[] { "开单收入", "执行收入" };
                if (request.ModuleName.IndexOf("开单收入") == -1 && request.ModuleName.IndexOf("执行收入") == -1)
                    throw new PerformanceException("模块名称规则错误");
                //if (!Regex.IsMatch(request.ModuleName, @"^[\u4e00-\u9fa5]+$"))
                //    throw new PerformanceException("模块名称规则错误，请使用全中文命名");

                var incomeList = exmoduleRepository.GetEntities(t => t.HospitalId == request.HospitalId && t.SheetType == (int)SheetType.Income);

                if (incomeList.Any(t => Regex.Replace(t.ModuleName, @"\d", "").Replace(".", "").Replace(" ", "") == request.ModuleName))
                    throw new PerformanceException("绩效模板已存在！");

                var moduleList = exmoduleRepository.GetEntities(t => t.HospitalId == request.HospitalId && t.ModuleName.IndexOf("1.") != -1);
                string name = request.ModuleName.Replace("开单收入", "").Replace("执行收入", "");
                var exist = moduleList.Where(t => t.ModuleName.Contains(name));
                if (exist != null && exist.Any())
                {
                    string modulename = exist.OrderByDescending(t => t.ModuleName).First().ModuleName;
                    int[] sort = Array.ConvertAll(modulename.Split(' ')[0].Split(new string[] { "." }, StringSplitOptions.RemoveEmptyEntries), t => ConvertHelper.TryInt(t));
                    sort[2] += 1;
                    addname = string.Join(".", sort) + " " + request.ModuleName;
                }
                else
                {
                    string modulename = moduleList.OrderByDescending(t => t.ModuleName).First().ModuleName;
                    int[] sort = Array.ConvertAll(modulename.Split(' ')[0].Split(new string[] { "." }, StringSplitOptions.RemoveEmptyEntries), t => ConvertHelper.TryInt(t));
                    sort[1] += 1;
                    addname = $"{sort[0]}.{sort[1]}.1 " + request.ModuleName;
                }
            }
            else if (request.SheetType == (int)SheetType.OtherWorkload)
            {
                var incomeList = exmoduleRepository.GetEntities(t => t.HospitalId == request.HospitalId && t.SheetType == (int)SheetType.OtherWorkload);

                if (incomeList != null && incomeList.Any(t => Regex.Replace(t.ModuleName, @"\d", "").Replace(".", "").Replace(" ", "") == request.ModuleName))
                    throw new PerformanceException("绩效模板已存在！");

                var moduleList = exmoduleRepository.GetEntities(t => t.HospitalId == request.HospitalId && t.ModuleName.IndexOf("3.") != -1);
                string modulename = moduleList.OrderByDescending(t => t.ModuleName).First().ModuleName;
                int[] sort = Array.ConvertAll(modulename.Split(' ')[0].Split(new string[] { "." }, StringSplitOptions.RemoveEmptyEntries), t => ConvertHelper.TryInt(t));
                sort[1] += 1;
                addname = $"{sort[0]}.{sort[1]} " + request.ModuleName;
            }
            else if (request.SheetType == (int)SheetType.Assess)
            {
                var incomeList = exmoduleRepository.GetEntities(t => t.HospitalId == request.HospitalId && t.SheetType == (int)SheetType.Assess);

                if (incomeList != null && incomeList.Any(t => Regex.Replace(t.ModuleName, @"\d", "").Replace(".", "").Replace(" ", "") == request.ModuleName))
                    throw new PerformanceException("绩效模板已存在！");

                var moduleList = exmoduleRepository.GetEntities(t => t.HospitalId == request.HospitalId && t.ModuleName.IndexOf("5.") != -1);
                string modulename = moduleList.OrderByDescending(t => t.ModuleName).First().ModuleName;
                int[] sort = Array.ConvertAll(modulename.Split(' ')[0].Split(new string[] { "." }, StringSplitOptions.RemoveEmptyEntries), t => ConvertHelper.TryInt(t));
                sort[1] += 1;
                addname = $"{sort[0]}.{sort[1]} " + request.ModuleName;
            }

            ex_module entity = new ex_module
            {
                ModuleName = addname,
                HospitalId = request.HospitalId,
                Description = request.Description,
                SheetType = request.SheetType,
                TypeId = request.TypeId,
                ReadOnly = 0,
            };
            if (!exmoduleRepository.Add(entity))
                throw new PerformanceException("添加失败！");
            return entity;
        }

        public ex_module EditModule(ModModuleRequest request)
        {
            var entity = exmoduleRepository.GetEntity(t => t.Id == request.ModuleId);
            if (entity == null)
                throw new PerformanceException("该绩效抽取方案不存在！");
            //if (entity.ReadOnly == 1)
            //    throw new PerformanceException("该绩效抽取方案不可编辑！");

            var list = exmoduleRepository.GetEntities(t => t.Id != entity.Id && t.HospitalId == entity.HospitalId && t.ModuleName == request.ModuleName);
            if (list != null && list.Any())
                throw new PerformanceException("绩效模板已存在！");

            entity.ModuleName = request.ModuleName ?? entity.ModuleName;
            entity.SheetType = request.SheetType;
            entity.Description = request.Description;
            entity.TypeId = request.TypeId;
            entity.ConfigId = request.ConfigId;
            if (!exmoduleRepository.Update(entity))
                throw new PerformanceException("修改失败！");

            return entity;
        }

        public void DelModule(int moduleId)
        {
            var entity = exmoduleRepository.GetEntity(t => t.Id == moduleId);
            if (entity == null)
                throw new PerformanceException("该绩效抽取方案不存在！");

            if (!exmoduleRepository.Remove(entity))
                throw new PerformanceException("删除失败！");
            if (entity.SheetType != (int)SheetType.SpecialUnit)
            {
                var itemList = exitemRepository.GetEntities(t => t.ModuleId == moduleId);
                if (itemList != null && itemList.Any())
                    exitemRepository.RemoveRange(itemList.ToArray());
            }
            else
            {
                var specialList = exspecialRepository.GetEntities(t => t.HospitalId == entity.HospitalId);
                if (specialList != null && specialList.Any())
                    exspecialRepository.RemoveRange(specialList.ToArray());
            }
        }

        #endregion Modules

        #region Items

        public List<ex_item> QueryItems(int moduleId)
        {
            var list = exitemRepository.GetEntities(t => t.ModuleId == moduleId);
            return list?.OrderBy(t => t.Id).ToList();
        }

        public List<ex_item> AddItem(ItemListRequest request)
        {
            var entity = exmoduleRepository.GetEntity(t => t.Id == request.ModuleId);
            if (entity == null)
                throw new PerformanceException("选择的绩效抽取方案不存在！");

            var list = request.Items;
            list.ForEach(t =>
            {
                t.ModuleId = entity.Id;
                //t.ExtractId = entity.ExtractId;
                t.ReadOnly = 0;
            });
            if (!exitemRepository.AddRange(list.ToArray()))
                throw new PerformanceException("添加失败！");

            return list;
        }

        public ex_item EditItem(ex_item entity)
        {
            var item = exitemRepository.GetEntity(t => t.Id == entity.Id); if (item == null)
                throw new PerformanceException("选择修改的项不存在！");

            item.ItemName = entity.ItemName;
            item.FactorValue1 = entity.FactorValue1;
            item.FactorValue2 = entity.FactorValue2;
            item.FactorValue3 = entity.FactorValue3;
            item.TypeId = entity.TypeId;
            item.ConfigId = entity.ConfigId;
            if (!exitemRepository.Update(item))
                throw new PerformanceException("修改失败！");

            return item;
        }

        public void DelItem(int itemId)
        {
            var item = exitemRepository.GetEntity(t => t.Id == itemId);
            if (item == null)
                throw new PerformanceException("Item项不存在！");

            exitemRepository.Remove(item);
        }

        #endregion Items

        #region 特殊科室

        /// <summary>
        /// 特殊科室模板配置项列表
        /// </summary>
        /// <returns></returns>
        public List<ex_special> QuerySpecial(int hospitalId)
        {
            var list = exspecialRepository.GetEntities(t => t.HospitalId == hospitalId);
            return list;
        }

        /// <summary>
        /// 特殊科室模板配置项新增
        /// </summary>
        /// <returns></returns>
        public List<ex_special> AddSpecial(SpecialListRequest request)
        {
            var list = request.Items;
            list.ForEach(t => t.HospitalId = request.HospitalId);
            if (!exspecialRepository.AddRange(list.ToArray()))
                throw new PerformanceException("添加失败！");

            return list;
        }

        /// <summary>
        /// 特殊科室模板配置项修改
        /// </summary>
        /// <returns></returns>
        public ex_special EditSpecial(ex_special entity)
        {
            var special = exspecialRepository.GetEntity(t => t.Id == entity.Id);
            if (special == null)
                throw new PerformanceException("选择修改的数据不存在！");

            special.Department = entity.Department ?? special.Department;
            special.Target = entity.Target;
            special.TargetFactor = entity.TargetFactor;
            special.AdjustFactor = entity.AdjustFactor;
            special.TypeId = entity.TypeId;
            special.ConfigId = entity.ConfigId;
            if (!exspecialRepository.Update(special))
                throw new PerformanceException("修改失败！");

            return special;
        }

        /// <summary>
        /// 特殊科室模板配置项删除
        /// </summary>
        /// <returns></returns>
        public void DelSpecial(int specialId)
        {
            var special = exspecialRepository.GetEntity(t => t.Id == specialId);
            if (special == null)
                throw new PerformanceException("需要删除的项不存在！");

            exspecialRepository.Remove(special);
        }

        #endregion 特殊科室

        public bool QueryHosConfigs(int moduleId, ref bool isSingle, out int sheetType)
        {
            var module = exmoduleRepository.GetEntity(t => t.Id == moduleId);
            if (module == null)
                throw new PerformanceException("绩效模板不存在，请重新选择！");

            sheetType = (int)module.SheetType;
            //if (module.SheetType != (int)SheetType.Income)
            //    throw new PerformanceException("当前模板不能进行考核项目自动添加");

            var hospital = hospitalRepository.GetEntity(t => t.ID == module.HospitalId);
            if (hospital == null) throw new PerformanceException("医院信息错误！");

            isSingle = hospital.IsSingleProject == 1;

            var hospitalConfigs = hospitalconfigRepository.GetEntities(t => t.HospitalId == module.HospitalId);
            if (hospitalConfigs != null && hospitalConfigs.Any())
                return true;

            return false;
        }

        /// <summary>
        /// 添加默认绩效模板配置
        /// </summary>
        /// <param name="moduleId"></param>
        public void AddItems(int moduleId)
        {
            var module = exmoduleRepository.GetEntity(t => t.Id == moduleId);
            if (module == null)
                throw new PerformanceException("绩效模板不存在，请重新选择！");

            if (module.SheetType != (int)SheetType.Income)
                return;

            var sqlconfig = moddicRepository.GetEntity(w => w.HospitalId == module.HospitalId && w.Type.Trim().ToLower() == "itemsql");
            if (sqlconfig != null)
            {
                var hospitalConfig = hospitalconfigRepository.GetEntity(t => t.HospitalId == module.HospitalId && t.Id == sqlconfig.ConfigId);
                if (hospitalConfig == null)
                {
                    logger.LogInformation("添加默认收费项时，医院配置信息未设置");
                    return;
                }
                QueryAndAddItem(new List<sys_hospitalconfig> { hospitalConfig }, sqlconfig.Content, module);
            }
            else
            {
                logger.LogInformation("添加默认收费项时医院未设置sql");
                var hospitalConfigs = hospitalconfigRepository.GetEntities(t => t.HospitalId == module.HospitalId);
                if (hospitalConfigs == null || !hospitalConfigs.Any())
                {
                    logger.LogInformation("医院未设置数据库连接信息");
                    return;
                }
                string sql = "SELECT ITEM_TYPE FROM DIC_FEE GROUP BY ITEM_TYPE ORDER BY ITEM_TYPE";
                QueryAndAddItem(hospitalConfigs, sql, module);
            }
        }

        private bool QueryAndAddItem(List<sys_hospitalconfig> hospitalconfigs, string sql, ex_module module)
        {
            logger.LogInformation("创建数据库连接");
            List<string> itemNames = new List<string>();
            foreach (var hospitalConfig in hospitalconfigs)
            {
                var connection = ConnectionBuilder.Create((DatabaseType)hospitalConfig.DataBaseType, hospitalConfig.DbSource, hospitalConfig.DbName, hospitalConfig.DbUser, hospitalConfig.DbPassword);
                logger.LogInformation($"执行sql：{sql}");
                try
                {
                    logger.LogInformation($"ConnectionString: {connection?.ConnectionString}");
                    var dataList = extractRepository.ExecuteScript(connection, sql, null);
                    logger.LogInformation($"获取数据{dataList?.Count ?? 0}条");
                    if (dataList != null && dataList.Any())
                        itemNames.AddRange(dataList.Select(t => t.Value.ToString()));
                }
                catch (Exception ex)
                {
                    logger.LogError(ex.ToString());
                }
            }

            var items = exitemRepository.GetEntities(t => t.ModuleId == module.Id);
            if (items == null && (itemNames == null || !itemNames.Any()))
                return true;

            var delItems = items?.Where(t => !itemNames.Contains(t.ItemName));
            if (delItems != null && delItems.Any())
            {
                logger.LogInformation($"删除默认收费项 受影响行数{delItems.Count()}");
                exitemRepository.RemoveRange(delItems.ToArray());
            }

            if (itemNames != null && itemNames.Any(t => !string.IsNullOrEmpty(t)))
            {
                if (items != null)
                    itemNames = itemNames.Except(items.Select(t => t.ItemName)).ToList();

                logger.LogInformation($"添加默认收费项 去重后数据有{itemNames.Distinct().Count()}");
                var itemList = itemNames.Where(t => !string.IsNullOrEmpty(t)).Distinct().Select(t => new ex_item
                {
                    ItemName = t.Trim(),
                    FactorValue1 = 0m,
                    FactorValue2 = 0m,
                    FactorValue3 = 0m,
                    ModuleId = module.Id,
                    TypeId = module.TypeId,
                    ReadOnly = 1
                });
                logger.LogInformation($"添加默认收费项 受影响行数{itemList.Count()}");
                return exitemRepository.AddRange(itemList.ToArray());
            }
            return true;
        }

        /// <summary>
        /// 特殊科室人均
        /// </summary>
        /// <returns></returns>
        public List<TitleValue> PerforType()
        {
            var list = EnumHelper.GetItems<PerforType>();
            var result = list.Select(t => new TitleValue
            {
                Title = t.Description,
                Value = t.Description
            });
            return result.ToList();
        }

        /// <summary>
        /// 获取抽取的配置
        /// </summary>
        /// <param name="hospitalId"></param>
        /// <returns></returns>
        public List<sys_hospitalconfig> GetHospitalconfigs(int hospitalId)
        {
            var configs = hospitalconfigRepository.GetEntities(t => t.HospitalId == hospitalId);
            return configs;
        }

        /// <summary>
        /// 绩效数据抽取模板
        /// </summary>
        /// <returns></returns>
        public List<TitleValue> ExtractScheme(int hospitalId, List<int> executeType, int? sheetType)
        {
            var titlevalue = new List<TitleValue>();
            Expression<Func<ex_type, bool>> exp = t => new List<int> { 0, hospitalId }.Contains(t.HospitalId);
            if (executeType.FirstOrDefault() == 1)
                exp = exp.And(t => t.Source == (int)SheetType.Income);
            else if (sheetType.HasValue && sheetType.Value != 0)
                exp = exp.And(t => t.Source == sheetType);
            else
                exp = exp.And(t => t.Source != (int)SheetType.Income);

            var list = extypeRepository.GetEntities(exp);
            if (list != null && list.Any())
            {
                //var scripts = exscriptRepository.GetEntities(t => list.Select(w => w.Id).Contains(t.TypeId));

                //titlevalue = list.Where(t => scripts.Select(w => w.TypeId).Contains(t.Id)).Select(t => new TitleValue
                //{
                //    Title = string.IsNullOrEmpty(t.Description) ? t.EName : $"{t.EName}({t.Description})",
                //    Value = t.Id.ToString()
                //}).OrderBy(t => t.Title).ToList();

                titlevalue = list.Select(t => new TitleValue
                {
                    Title = string.IsNullOrEmpty(t.Description) ? t.EName : $"{t.EName}({t.Description})",
                    Value = t.Id.ToString()
                }).OrderBy(t => t.Title).ToList();
            }

            return titlevalue;
        }

        /// <summary>
        /// 费用类型
        /// </summary>
        /// <returns></returns>
        public List<TitleValue> FeeType()
        {
            var titlevalue = new List<TitleValue>();
            var type = EnumHelper.GetItems<SheetType>().Where(t => new List<int>
            {
                (int)SheetType.Income,
                (int)SheetType.OtherIncome,
                (int)SheetType.Expend,
                (int)SheetType.Workload,
                (int)SheetType.SpecialUnit,
                (int)SheetType.OtherWorkload
            }.Contains(t.Value));
            if (type != null && type.Any())
            {
                titlevalue = type.Select(t => new TitleValue
                {
                    Title = t.Description,
                    Value = t.Value.ToString()
                }).ToList();
            }
            return titlevalue;
        }

        /// <summary>
        /// 绩效考核项费用来源
        /// </summary>
        /// <returns></returns>
        public ModFeeResponse FeeSource(ModModuleRequest request)
        {
            var configList = hospitalconfigRepository.GetEntities(t => t.HospitalId == request.HospitalId);
            if (configList != null && configList.Any())
            {
                var hospitalConfig = configList.First();
                var connection = ConnectionBuilder.Create(DatabaseType.SqlServer, hospitalConfig.DbSource, hospitalConfig.DbName, hospitalConfig.DbUser, hospitalConfig.DbPassword);
                int pagesize = 500, pagenum = 0;
                if (request.PageNum != 0)
                    pagenum = request.PageNum - 1;
                if (request.PageSize >= 500 && request.PageSize <= 10000)
                    pagesize = request.PageSize;

                string sql = $"select top {pagesize} t1.* from (select row_number() over(order by charge_name) as rownumber,* from (select min(code) code,charge_name from dic_fee where charge_name is not null and charge_name != '' group by charge_name)t )t1 where rownumber> {pagenum} * {pagesize};";
                var dataList = extractRepository.ExecuteScript(connection, sql, null);
                if (dataList != null && dataList.Any())
                {
                    var list = new List<TitleValue>();
                    foreach (var num in dataList.Select(t => t.RowNumber).Distinct())
                    {
                        var data = new TitleValue
                        {
                            Title = dataList.First(t => t.RowNumber == num && t.ColumnName.ToLower() == "charge_name").Value.ToString(),
                            Value = dataList.First(t => t.RowNumber == num && t.ColumnName.ToLower() == "code").Value.ToString(),
                        };
                        list.Add(data);
                    }
                    sql = $"select count(*) num from (select min(code) code,charge_name from dic_fee where charge_name is not null and charge_name != '' group by charge_name)t ;";
                    connection = ConnectionBuilder.Create(DatabaseType.SqlServer, hospitalConfig.DbSource, hospitalConfig.DbName, hospitalConfig.DbUser, hospitalConfig.DbPassword);
                    dataList = extractRepository.ExecuteScript(connection, sql, null);
                    return new ModFeeResponse
                    {
                        Total = (int)dataList.FirstOrDefault().Value,
                        PageNum = pagenum + 1,
                        PageSize = pagesize,
                        Data = list
                    };
                }
            }

            return new ModFeeResponse();
        }

        #region 配置校验

        public string LastAllotFilePath(int allotId)
        {
            // 获取绩效信息
            var allot = perallotRepository.GetEntity(t => t.ID == allotId);
            if (allot == null)
                throw new PerformanceException("AllotID错误");

            var statesArray = new int[] { (int)AllotStates.GenerateSucceed, (int)AllotStates.Archive };
            var allotList = perallotRepository.GetEntities(t => t.HospitalId == allot.HospitalId && statesArray.Contains(t.States));
            var allotLast = allotList?.OrderByDescending(t => t.Year).ThenByDescending(t => t.Month).First();
            if (allotLast != null)
                return allotLast.Path;

            return "";
        }

        /// <summary>
        /// 配置校验
        /// </summary>
        /// <param name="allotId"></param>
        /// <param name="hospitalId"></param>
        /// <param name="useTemplate"></param>
        public string Judge(int allotId, int hospitalId, int useTemplate, ref bool isSingle, out string filePath)
        {
            string result = null;
            filePath = "";
            try
            {
                // 获取绩效信息
                var allot = perallotRepository.GetEntity(t => t.ID == allotId);
                if (allot == null)
                    throw new PerformanceException("AllotID错误");
                // 获取医院信息
                var hospital = hospitalRepository.GetEntity(t => t.ID == hospitalId);
                if (hospital == null)
                    throw new PerformanceException("医院ID错误");
                isSingle = (hospital.IsSingleProject ?? 2) == 1;
                // 获取医院配置信息
                var hospitalConfigList = hospitalconfigRepository.GetEntities(t => t.HospitalId == hospitalId);
                if (hospitalConfigList == null || hospitalConfigList.Count == 0)
                    throw new PerformanceException("当前医院暂不支持HIS数据抽取");
                // 获取最近一次绩效
                var statesArray = new int[] { (int)AllotStates.GenerateSucceed, (int)AllotStates.Archive };
                var allotList = perallotRepository.GetEntities(t => t.HospitalId == hospitalId && statesArray.Contains(t.States));
                var allotLast = allotList?.OrderByDescending(t => t.Year).ThenByDescending(t => t.Month).First();
                if (allotLast != null)
                    filePath = allotLast.Path;
                // 获取当前医院模版信息
                var modulesList = exmoduleRepository.GetEntities(t => t.HospitalId == hospitalId);
                if (modulesList == null || modulesList.Count == 0)
                    throw new PerformanceException("当前医院还未配置模版");
                // 获取模板项
                var moduleIdList = modulesList.Select(t => t.Id).ToList();
                var itemsList = exitemRepository.GetEntities(t => t.ModuleId.HasValue && moduleIdList.Contains(t.ModuleId.Value));
                if (itemsList == null || itemsList.Count == 0)
                    throw new PerformanceException("当前医院还未配置模版项");
                // 获取当前模板所有相关抽取SQL语句
                var extypeIds = itemsList.Select(t => t.TypeId).Union(modulesList.Select(t => t.TypeId)).Distinct().ToList();
                var extractList = exscriptRepository.GetEntities(t => extypeIds.Contains(t.TypeId));
                if (extractList == null || extractList.Count == 0)
                    throw new PerformanceException("当前医院配置模板无需抽取");
            }
            catch (PerformanceException ex)
            {
                logger.LogError($"提取绩效数据异常 {ex.ToString()}");
                result = ex.Message;
            }
            catch (Exception ex)
            {
                logger.LogError($"提取绩效数据异常 {ex.ToString()}");
                throw new Exception(ex.Message);
            }
            return result;
        }

        #endregion 配置校验

        #region 检查是否有新增的科室或费用类别

        public Dictionary<string, object> CheckHasNewDepartmentOrCategory(int allotId)
        {
            var allot = perallotRepository.GetEntity(t => t.ID == allotId);

            var allotList = perallotRepository.GetEntities(t => t.HospitalId == allot.HospitalId && new int[] { (int)AllotStates.GenerateSucceed, (int)AllotStates.Archive }.Contains(t.States));
            var prevAllot = allotList?.OrderByDescending(t => t.Year).ThenByDescending(t => t.Month).First();
            if (prevAllot == null) return null;

            var modDics = moddicRepository.GetEntities(t => t.HospitalId == allot.HospitalId && t.Type == "checksql");
            if (modDics == null || !modDics.Any()) return null;

            var hospitalconfigs = hospitalconfigRepository.GetEntities(t => modDics.Select(s => s.ConfigId).Distinct().Contains(t.Id));
            if (hospitalconfigs == null || !hospitalconfigs.Any()) return null;

            var sheets = persheetRepository.GetEntities(t => t.AllotID == prevAllot.ID && t.SheetType == (int)SheetType.Income) ?? new List<per_sheet>();
            var importdata = imdataRepository.GetEntities(t => sheets.Select(s => s.ID).Contains(t.SheetID.Value)) ?? new List<im_data>();

            Dictionary<string, object> paramtemers = new Dictionary<string, object>();
            foreach (var dic in modDics)
            {
                if (paramtemers.ContainsKey(dic.Remark)) continue;

                var config = hospitalconfigs.FirstOrDefault(t => t.Id == dic.ConfigId);
                if (config == null) continue;

                var data = queryService.QueryData(config, allot, dic.Content);
                if (data == null || !data.Any()) continue;

                var sheet = sheets.FirstOrDefault(t => t.SheetName.Contains(dic.Remark));
                if (sheet == null) continue;

                var sheetdata = importdata.Where(t => t.SheetID == sheet.ID)?.ToList() ?? new List<im_data>();

                var departments = sheetdata.Select(t => t.Department).Distinct();
                var noExistedDepartment = data.Select(t => t.Department).Distinct().Except(departments);

                var typenames = sheetdata.Select(t => t.TypeName).Distinct();
                var noExistedTypename = data.Select(t => t.Category).Distinct().Except(typenames);

                StringBuilder stringBuilder = new StringBuilder();

                if (noExistedDepartment != null && noExistedDepartment.Any())
                    stringBuilder.AppendLine($"新增科室：{string.Join(",", noExistedDepartment)}");

                if (noExistedTypename != null && noExistedTypename.Any())
                    stringBuilder.AppendLine($"新增费用类型：{string.Join(",", noExistedTypename)}");

                paramtemers.Add(dic.Remark, stringBuilder.ToString());
            }
            return paramtemers;
        }

        #endregion 检查是否有新增的科室或费用类别
    }
}
