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

namespace Performance.Services
{
    public class ModExtractService : IAutoInjection
    {
        private readonly ILogger<ModExtractService> logger;
        private PerforModextractRepository perforModextractRepository;
        private PerforModitemRepository perforModitemRepository;
        private PerforModmoduleRepository perforModmoduleRepository;
        private PerforModspecialRepository perforModspecialRepository;
        private PerforHospitalconfigRepository perforHospitalconfigRepository;
        private PerforExtractRepository perforExtractRepository;
        private PerforModdicRepository moddicRepository;

        public ModExtractService(
            ILogger<ModExtractService> logger,
            PerforModextractRepository perforModextractRepository,
            PerforModitemRepository perforModitemRepository,
            PerforModmoduleRepository perforModmoduleRepository,
            PerforModspecialRepository perforModspecialRepository,
            PerforHospitalconfigRepository perforHospitalconfigRepository,
            PerforExtractRepository perforExtractRepository,
            PerforModdicRepository moddicRepository)
        {
            this.logger = logger;
            this.perforModextractRepository = perforModextractRepository;
            this.perforModitemRepository = perforModitemRepository;
            this.perforModmoduleRepository = perforModmoduleRepository;
            this.perforModspecialRepository = perforModspecialRepository;
            this.perforHospitalconfigRepository = perforHospitalconfigRepository;
            this.perforExtractRepository = perforExtractRepository;
            this.moddicRepository = moddicRepository;
        }

        /// <summary>
        /// 绩效数据抽取模板
        /// </summary>
        /// <returns></returns>
        public List<TitleValue> ExtractScheme(int hospitalId, List<int> executeType)
        {
            var titlevalue = new List<TitleValue>();
            var list = perforModextractRepository.GetEntities(t => (t.HospitalId == hospitalId || t.HospitalId == null) && executeType.Contains(t.ExecuteType.Value));
            if (list != null && list.Any())
                titlevalue = list.OrderBy(t => t.EName).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 }.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 mod_module AddModule(ModModuleRequest request)
        {
            if (request.SheetType != (int)SheetType.Income)
                throw new PerformanceException("模块类型错误，只支持收入模板配置");

            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 = perforModmoduleRepository.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("绩效模板已存在！");

            string addname = "";
            var moduleList = perforModmoduleRepository.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;
            }

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

        /// <summary>
        /// 费用字典
        /// </summary>
        /// <returns></returns>
        public List<mod_module> Module(int hospitalId)
        {
            //首次添加费用字典默认值
            AddModule(hospitalId);

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

        /// <summary>
        /// 首次添加费用字典默认值
        /// </summary>
        /// <param name="hospitalId"></param>
        private void AddModule(int hospitalId)
        {
            var moduleList = new mod_module[]
            {
                new mod_module{ ModuleName = "1.0.1 额外收入", SheetType = (int)SheetType.OtherIncome },
                new mod_module{ ModuleName = "1.1.1 门诊开单收入", SheetType = (int)SheetType.Income },
                new mod_module{ ModuleName = "1.1.2 门诊执行收入", SheetType = (int)SheetType.Income },
                new mod_module{ ModuleName = "1.2.1 住院开单收入", SheetType = (int)SheetType.Income },
                new mod_module{ ModuleName = "1.2.2 住院执行收入", SheetType = (int)SheetType.Income },
                new mod_module{ ModuleName = "2.1 成本支出统计表", SheetType = (int)SheetType.Expend },
                new mod_module{ ModuleName = "3.1 医生组工作量绩效测算表", SheetType = (int)SheetType.Workload },
                new mod_module{ ModuleName = "3.2 护理组工作量绩效测算表", SheetType = (int)SheetType.Workload },
            };

            var data = perforModmoduleRepository.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<mod_module> modules = new List<mod_module>();
                foreach (var item in inexistence)
                {
                    var module = new mod_module
                    {
                        HospitalId = hospitalId,
                        ModuleName = item.ModuleName,
                        SheetType = (int)item.SheetType,
                        ReadOnly = 1,
                        ExtractId = null,
                        IsGenerated = 0
                    };
                    modules.Add(module);
                }
                if (modules.Any())
                    perforModmoduleRepository.AddRange(modules.ToArray());
            }
        }

        /// <summary>
        /// 绩效模板修改
        /// </summary>
        /// <returns></returns>
        public mod_module EditModule(ModModuleRequest request)
        {
            var entity = perforModmoduleRepository.GetEntity(t => t.Id == request.ModuleId);
            if (entity == null)
                throw new PerformanceException("该绩效抽取方案不存在！");
            //if (entity.ReadOnly == 1)
            //    throw new PerformanceException("该绩效抽取方案不可编辑！");

            var list = perforModmoduleRepository.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.ExtractId = request.ExtractId;
            entity.ConfigId = request.ConfigId;
            if (!perforModmoduleRepository.Update(entity))
                throw new PerformanceException("修改失败！");

            return entity;
        }

        /// <summary>
        /// 绩效模板删除
        /// </summary>
        /// <returns></returns>
        public void DelModule(int moduleId)
        {
            var entity = perforModmoduleRepository.GetEntity(t => t.Id == moduleId);
            if (entity == null)
                throw new PerformanceException("该绩效抽取方案不存在！");

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

        /// <summary>
        /// 绩效收入模板配置项列表
        /// </summary>
        /// <returns></returns>
        public List<mod_item> Items(int moduleId)
        {
            var list = perforModitemRepository.GetEntities(t => t.ModuleId == moduleId);
            return list?.OrderBy(t => t.Id).ToList();
        }

        /// <summary>
        /// 绩效收入模板配置项新增
        /// </summary>
        /// <returns></returns>
        public List<mod_item> AddItem(ItemListRequest request)
        {
            var entity = perforModmoduleRepository.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 (!perforModitemRepository.AddRange(list.ToArray()))
                throw new PerformanceException("添加失败！");

            return list;
        }

        /// <summary>
        /// 绩效收入模板配置项修改
        /// </summary>
        /// <returns></returns>
        public mod_item EditItem(mod_item entity)
        {
            var item = perforModitemRepository.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.ExtractId = entity.ExtractId;
            item.SelectionRange = entity.SelectionRange;
            item.ConfigId = entity.ConfigId;
            if (!perforModitemRepository.Update(item))
                throw new PerformanceException("修改失败！");

            return item;
        }

        /// <summary>
        /// 绩效收入模板配置项删除
        /// </summary>
        /// <returns></returns>
        public void DelItem(int itemId)
        {
            var item = perforModitemRepository.GetEntity(t => t.Id == itemId);
            if (item == null)
                throw new PerformanceException("Item项不存在！");

            perforModitemRepository.Remove(item);
        }

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

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

            return list;
        }

        /// <summary>
        /// 特殊科室模板配置项修改
        /// </summary>
        /// <returns></returns>
        public mod_special EditSpecial(mod_special entity)
        {
            var special = perforModspecialRepository.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.ExtractId = entity.ExtractId;
            special.ConfigId = entity.ConfigId;
            if (!perforModspecialRepository.Update(special))
                throw new PerformanceException("修改失败！");

            return special;
        }

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

            perforModspecialRepository.Remove(special);
        }





        /// <summary>
        /// 绩效考核项费用来源
        /// </summary>
        /// <returns></returns>
        public ModFeeResponse FeeSource(ModModuleRequest request)
        {
            var configList = perforHospitalconfigRepository.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 = perforExtractRepository.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 = perforExtractRepository.ExecuteScript(connection, sql, null);
                    return new ModFeeResponse
                    {
                        Total = (int)dataList.FirstOrDefault().Value,
                        PageNum = pagenum + 1,
                        PageSize = pagesize,
                        Data = list
                    };
                }
            }

            return new ModFeeResponse();
        }

        /// <summary>
        /// 添加默认绩效模板配置
        /// </summary>
        /// <param name="moduleId"></param>
        public void AddItems(int moduleId)
        {
            var module = perforModmoduleRepository.GetEntity(t => t.Id == moduleId);
            if (module == null)
                throw new PerformanceException("绩效模板不存在，请重新选择！");
            //收入  默认添加收费项
            if ((int)SheetType.Income == module.SheetType && module.IsGenerated == 0)
            {
                var sqlconfig = moddicRepository.GetEntity(w => w.HospitalId == module.HospitalId && w.Type.Trim().ToLower() == "itemsql");
                if (sqlconfig == null)
                {
                    logger.LogInformation("{0} 医院配置信息未设置", "添加默认收费项");
                    throw new PerformanceException($"医院配置信息未设置");
                }
                var hospitalConfig = perforHospitalconfigRepository.GetEntity(t => t.HospitalId == module.HospitalId && t.Id == sqlconfig.ConfigId);
                if (hospitalConfig == null)
                {
                    logger.LogInformation("{0} 医院配置信息未设置", "添加默认收费项");
                    throw new PerformanceException($"医院配置信息未设置");
                }

                logger.LogInformation("创建数据库连接");
                var connection = ConnectionBuilder.Create(DatabaseType.Oracle, hospitalConfig.DbSource, hospitalConfig.DbName, hospitalConfig.DbUser, hospitalConfig.DbPassword);
                string sql = sqlconfig.Content;
                logger.LogInformation($"执行sql：{sql}");
                var dataList = perforExtractRepository.ExecuteScript(connection, sql, null);
                logger.LogInformation($"获取数据{dataList?.Count ?? 0}条");
                if (dataList != null && dataList.Any())
                {
                    var itemList = dataList.Select(t => new mod_item
                    {
                        ItemName = t.Value.ToString(),
                        FactorValue1 = 0m,
                        FactorValue2 = 0m,
                        FactorValue3 = 0m,
                        ModuleId = module.Id,
                        ExtractId = module.ExtractId,
                        ReadOnly = 1
                    });
                    logger.LogInformation($"添加默认收费项 受影响行数{itemList.Count()}");
                    perforModitemRepository.AddRange(itemList.ToArray());
                    module.IsGenerated = 1;
                    perforModmoduleRepository.Update(module);
                }
            }
        }

        /// <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 = perforHospitalconfigRepository.GetEntities(t => t.HospitalId == hospitalId);
            return configs;
        }
    }
}
