using AutoMapper;
using Masuit.Tools;
using Masuit.Tools.Models;
using Microsoft.AspNetCore.Hosting;
using Microsoft.AspNetCore.Http;
using Microsoft.Extensions.Logging;
using Newtonsoft.Json;
using OfficeOpenXml;
using OfficeOpenXml.Style;
using Performance.DtoModels;
using Performance.DtoModels.Request;
using Performance.EntityModels;
using Performance.EntityModels.Other;
using Performance.Infrastructure;
using Performance.Repository;
using System;
using System.Collections.Generic;
using System.Data;
using System.IO;
using System.Linq;
using System.Reflection;

namespace Performance.Services
{
    public class AssessNewService : IAutoInjection
    {
        private readonly IMapper mapper;
        private readonly ILogger<AssessNewService> logger;
        private readonly IWebHostEnvironment evn;
        private readonly PerforUserRepository _userRepository;
        private readonly PerforCofaccountingRepository cofaccountingRepository;
        private readonly PerforPerallotRepository perforPerallotRepository;
        private readonly PerforPerAssessCategoryRepository perforPerAssessCategoryRepository;
        private readonly PerforPerAssessSchemeRepository perforPerAssessSchemeRepository;
        private readonly PerforPerAssessSchemeItemsRepository perforPerAssessSchemeItemsRepository;
        private readonly PerforPerAssessSchemeTargetRepository perforPerAssessSchemeTargetRepository;
        private readonly PerforPerAssessIssueSchemeRepository perforPerAssessIssueSchemeRepository;

        public AssessNewService(
                IMapper mapper,
                ILogger<AssessNewService> logger,
                IWebHostEnvironment evn,
                PerforPerAssessCategoryRepository perforPerAssessCategoryRepository,
                PerforPerallotRepository perforPerallotRepository,
                PerforPerAssessSchemeRepository perforPerAssessSchemeRepository,
                PerforPerAssessSchemeItemsRepository perforPerAssessSchemeItemsRepository,
                PerforPerAssessSchemeTargetRepository perforPerAssessSchemeTargetRepository,
                PerforCofaccountingRepository cofaccountingRepository,
                PerforPerAssessIssueSchemeRepository perforPerAssessIssueSchemeRepository,
                PerforUserRepository userRepository
             )
        {
            this.mapper = mapper;
            this.logger = logger;
            this.evn = evn;
            this.perforPerAssessCategoryRepository = perforPerAssessCategoryRepository;
            this.perforPerallotRepository = perforPerallotRepository;
            this.perforPerAssessSchemeRepository = perforPerAssessSchemeRepository;
            this.perforPerAssessSchemeItemsRepository = perforPerAssessSchemeItemsRepository;
            this.perforPerAssessSchemeTargetRepository = perforPerAssessSchemeTargetRepository;
            this.cofaccountingRepository = cofaccountingRepository;
            this.perforPerAssessIssueSchemeRepository = perforPerAssessIssueSchemeRepository;
            _userRepository = userRepository;
        }
        #region 考核类别
        public ApiResponse<List<per_assess_category>> CategoryList(int allotId)
        {
            var result = perforPerAssessCategoryRepository.GetEntities(t => t.AllotId == allotId);
            if (result != null)
                result = result.OrderByDescending(w => w.UpdateTime).ToList();
            return new ApiResponse<List<per_assess_category>>(ResponseType.OK, result);
        }
        public ApiResponse CategoryAdd(AddAssessCategoryRequest request, int userid)
        {
            var allot = perforPerallotRepository.GetEntity(w => w.ID == request.AllotId);
            if (allot == null)
                throw new PerformanceException("当前绩效记录不存在");
            var categoryData = perforPerAssessCategoryRepository.GetEntities();
            var temp = categoryData.FirstOrDefault(w => w.AllotId == request.AllotId && w.AssessName == request.Category);
            if (temp != null)
                throw new PerformanceException("当前考核类别已存在");
            int codeMax = 0;
            if (categoryData.Any())
                int.TryParse(categoryData.Max(w => w.AssessCode.Substring(1)), out codeMax);
            string assessCode = codeMax <= 99 ? $"A{(codeMax + 1):D3}" : $"A{codeMax + 1}";
            var dateTime = DateTime.Now;
            var per_assess_category = new per_assess_category()
            {
                AllotId = request.AllotId,
                AssessCode = assessCode,
                AssessName = request.Category,
                CreateBy = userid,
                CreateTime = dateTime,
                UpdateBy = userid,
                UpdateTime = dateTime,
            };
            if (perforPerAssessCategoryRepository.Add(per_assess_category))
                return new ApiResponse(ResponseType.OK, "添加成功");
            else return new ApiResponse(ResponseType.Fail, "添加失败");
        }
        public ApiResponse CategoryUpdate(UpdateAssessCategoryRequest request, int userid)
        {
            var allot = perforPerallotRepository.GetEntity(w => w.ID == request.AllotId);
            if (allot == null)
                throw new PerformanceException("当前绩效记录不存在");
            var any = perforPerAssessCategoryRepository.GetEntity(w => w.Id == request.CategoryId);
            if (any == null)
                throw new PerformanceException("当前操作错误，请刷新后重试");
            any.AllotId = request.AllotId;
            any.AssessName = request.Category;
            any.UpdateBy = userid;
            var dateTime = DateTime.Now;
            any.UpdateTime = dateTime;
            if (perforPerAssessCategoryRepository.Update(any))
                return new ApiResponse(ResponseType.OK, "修改成功");
            else return new ApiResponse(ResponseType.Fail, "修改失败");
        }
        public ApiResponse CategoryDelete(BatchAssessCategoryRequest request)
        {
            var temp = perforPerAssessSchemeRepository.GetEntity(w => request.CategoryId.Contains(w.AssessId));
            if (temp != null || temp?.Id > 0)
                throw new PerformanceException("请先删除类别下的方案");
            var any = perforPerAssessCategoryRepository.GetEntities(w => request.CategoryId.Contains(w.Id));
            if (any == null)
                throw new PerformanceException("当前操作错误，请刷新后重试");
            if (perforPerAssessCategoryRepository.RemoveRange(any.ToArray()))
                return new ApiResponse(ResponseType.OK, "删除成功");
            else return new ApiResponse(ResponseType.Fail, "删除失败");
        }
        public ApiResponse<List<PerAssessmentStatisticsResponse>> CategoryIssueCheck(UpdateAssessCategoryRequest request)
        {
            var allot = perforPerallotRepository.GetEntity(w => w.ID == request.AllotId);
            if (allot == null)
                throw new PerformanceException("当前绩效记录不存在");
            var issueDatas = perforPerallotRepository.GetAssessIssue(request.AllotId);
            var issueSchemeDatas = perforPerAssessIssueSchemeRepository.GetEntities(w => w.AllotId == request.AllotId);
            if (request.CategoryId > 0)
            {
                issueDatas = issueDatas.Where(w => w.AssessId == request.CategoryId).ToList();
                issueSchemeDatas = issueSchemeDatas.Where(w => w.AssessId == request.CategoryId).ToList();
            }
            if (request.SchemeId > 0)
            {
                issueDatas = issueDatas.Where(w => w.SchemeId == request.SchemeId).ToList();
                issueSchemeDatas = issueSchemeDatas.Where(w => w.SchemeId == request.SchemeId).ToList();
            }
            if (issueDatas.Count() <= 0 || !issueDatas.Any())
                throw new PerformanceException("未设置考核内容或未设置考核单元！");
            var statisticdates = new List<PerAssessmentStatisticsResponse>();
            Func<per_assess_issue_scheme, view_assess_issue, bool> func = (schemes, issues) =>
            {
                var result =
schemes.AssessId == issues.AssessId &&
schemes.AssessCode == issues.AssessCode &&
schemes.AssessName == issues.AssessName &&
schemes.SchemeCode == issues.SchemeCode &&
schemes.SchemeName == issues.SchemeName &&
schemes.ItemCode == issues.ItemCode &&
schemes.ItemName1 == issues.ItemName1 &&
schemes.ItemName2 == issues.ItemName2 &&
schemes.AssessScore == issues.AssessScore &&
schemes.AssessNorm == issues.AssessNorm &&
schemes.UnitCode == issues.UnitCode &&
schemes.UnitType == issues.UnitType &&
schemes.AccountingUnit == issues.AccountingUnit &&
schemes.TargetUnitCode == issues.TargetUnitCode &&
schemes.TargetUnitType == issues.TargetUnitType &&
schemes.TargetAccountingUnit == issues.TargetAccountingUnit;
                return result;
            };
            statisticdates = issueDatas.Select(issue =>
            {
                var issueData = issueDatas.SingleOrDefault(w => w.ItemCode == issue.ItemCode && w.TargetUnitType == issue.TargetUnitType && w.TargetAccountingUnit == issue.TargetAccountingUnit);
                var issueschemeData = issueSchemeDatas.SingleOrDefault(w => w.ItemCode == issue.ItemCode && w.TargetUnitType == issue.TargetUnitType && w.TargetAccountingUnit == issue.TargetAccountingUnit);
                if (issueschemeData == null)
                    return new PerAssessmentStatisticsResponse(issueData);
                if (issueschemeData != null && issueData != null)
                {
                    if (func(issueschemeData, issueData)) return null;
                    return new PerAssessmentStatisticsResponse(issueData)
                    {
                        Id = issueschemeData.Id,
                        OperationType = (int)Attendance.OperationType.修改,
                        Describe = "修改数据",
                    };
                }
                return null;
            }).ToList();
            foreach (var scheme in issueSchemeDatas)
            {
                var issueData = issueDatas.SingleOrDefault(w => w.ItemCode == scheme.ItemCode && w.TargetUnitType == scheme.TargetUnitType && w.TargetAccountingUnit == scheme.TargetAccountingUnit);
                var issueschemeData = issueSchemeDatas.SingleOrDefault(w => w.ItemCode == scheme.ItemCode && w.TargetUnitType == scheme.TargetUnitType && w.TargetAccountingUnit == scheme.TargetAccountingUnit);
                if (issueData == null)
                {
                    statisticdates.Add(new PerAssessmentStatisticsResponse(issueschemeData));
                }
            }
            statisticdates = statisticdates.Where(r => r != null).ToList();
            return new ApiResponse<List<PerAssessmentStatisticsResponse>>(ResponseType.OK, statisticdates);
        }
        //考核下发（把当前考核类别下所有方案下发）
        public ApiResponse CategoryIssueConfirm(UpdateAssessCategoryRequest request, int userid)
        {
            var categoryIssueCheck = CategoryIssueCheck(request).Data;
            if (categoryIssueCheck == null)
                throw new PerformanceException("暂无数据需要下发");
            var schemedatas = perforPerAssessIssueSchemeRepository.GetEntities(w => w.AllotId == request.AllotId);
            if (request.CategoryId > 0)
            {
                schemedatas = schemedatas.Where(w => w.AssessId == request.CategoryId).ToList();
            }
            if (request.SchemeId > 0)
            {
                schemedatas = schemedatas.Where(w => w.SchemeId == request.SchemeId).ToList();
            }
            var insertIssueChecks = categoryIssueCheck.Where(w => w.OperationType == (int)Attendance.OperationType.新增).ToList();
            var updateIssueChecks = categoryIssueCheck.Where(w => w.OperationType == (int)Attendance.OperationType.修改).ToList();
            var deleteIssueChecks = categoryIssueCheck.Where(w => w.OperationType == (int)Attendance.OperationType.删除).Select(w => w.Id).ToList();
            var dateTime = DateTime.Now;
            if (insertIssueChecks.Any())
            {
                var inserts = insertIssueChecks.Select(item =>
                {
                    return new per_assess_issue_scheme()
                    {
                        AllotId = item.AllotId,
                        AssessId = item.AssessId,
                        AssessCode = item.AssessCode,
                        AssessName = item.AssessName,
                        SchemeId = item.SchemeId,
                        SchemeCode = item.SchemeCode,
                        SchemeName = item.SchemeName,
                        ItemId = item.ItemId,
                        ItemCode = item.ItemCode,
                        ItemName1 = item.ItemName1,
                        ItemName2 = item.ItemName2,
                        AssessScore = item.AssessScore,
                        AssessNorm = item.AssessNorm,
                        UnitCode = item.UnitCode,
                        UnitType = item.UnitType,
                        Score = null,
                        ScoreRemark = "",
                        AccountingUnit = item.AccountingUnit,
                        TargetUnitCode = item.TargetUnitCode,
                        TargetUnitType = item.TargetUnitType,
                        TargetAccountingUnit = item.TargetAccountingUnit,
                        State = (int)Assess.AssessState.未提交,
                        CreateBy = userid,
                        CreateTime = dateTime,
                        UpdateBy = userid,
                        UpdateTime = dateTime,
                    };
                }).ToList();
                perforPerAssessIssueSchemeRepository.AddRange(inserts.ToArray());

            }
            if (updateIssueChecks.Any())
            {
                List<per_assess_issue_scheme> updateIssuedates = new List<per_assess_issue_scheme>();
                foreach (var item in updateIssueChecks)
                {
                    var data = schemedatas.FirstOrDefault(w => w.Id == item.Id);
                    if (data == null) continue;
                    data.AllotId = item.AllotId;
                    data.AssessId = item.AssessId;
                    data.AssessCode = item.AssessCode;
                    data.AssessName = item.AssessName;
                    data.SchemeId = item.SchemeId;
                    data.SchemeCode = item.SchemeCode;
                    data.SchemeName = item.SchemeName;
                    data.ItemId = item.ItemId;
                    data.ItemCode = item.ItemCode;
                    data.ItemName1 = item.ItemName1;
                    data.ItemName2 = item.ItemName2;
                    data.AssessScore = item.AssessScore;
                    data.AssessNorm = item.AssessNorm;
                    data.UnitCode = item.UnitCode;
                    data.UnitType = item.UnitType;
                    data.Score = null;
                    data.ScoreRemark = "";
                    data.AccountingUnit = item.AccountingUnit;
                    data.TargetUnitCode = item.TargetUnitCode;
                    data.TargetUnitType = item.TargetUnitType;
                    data.TargetAccountingUnit = item.TargetAccountingUnit;
                    data.State = (int)Assess.AssessState.未提交;
                    data.UpdateBy = userid;
                    data.UpdateTime = dateTime;
                    data.SubmitBy = null;
                    data.SubmitTime = null;
                    data.AuditBy = null;
                    data.AuditTime = null;
                    data.AuditRemark = null;
                    updateIssuedates.Add(data);
                }
                perforPerAssessIssueSchemeRepository.UpdateRange(updateIssuedates.ToArray());
            }
            if (deleteIssueChecks.Any())
            {
                var daletes = schemedatas.Where(w => deleteIssueChecks.Contains(w.Id)).ToList();
                perforPerAssessIssueSchemeRepository.RemoveRange(daletes.ToArray());
            }
            perforPerallotRepository.PerAssessIssueSchemeBackup(request.AllotId);
            return new ApiResponse(ResponseType.OK, "下发成功");
        }
        #endregion
        #region 考核方案       
        public PagedList<AssessSchemeDataResponse> SchemeList(QuerySchemeList query)
        {
            var scheme = perforPerAssessSchemeRepository.GetEntities(t => t.AllotId == query.AllotId);
            var category = perforPerAssessCategoryRepository.GetEntities(t => t.AllotId == query.AllotId);
            if (query.CategoryId > 0)
            {
                scheme = scheme.Where(w => w.AssessId == query.CategoryId).ToList();
                category = category.Where(w => w.Id == query.CategoryId).ToList();
            }
            var result = mapper.Map<List<AssessSchemeDataResponse>>(scheme);
            foreach (var item in result)
            {
                item.AssessCode = category.FirstOrDefault(w => w.Id == item.AssessId).AssessCode;
                item.AssessName = category.FirstOrDefault(w => w.Id == item.AssessId).AssessName;
            }
            result = result.OrderByDescending(w => w.UpdateTime).ToList();
            if (!string.IsNullOrEmpty(query.SchemeName))
                result = result.Where(w => w.SchemeName.Contains(query.SchemeName)).ToList();
            var totalItems = result.Count();
            var pagedIssueSchemes = result.Skip((query.Page - 1) * query.PageSize).Take(query.PageSize).ToList();
            return new PagedList<AssessSchemeDataResponse>(pagedIssueSchemes, query.Page, query.PageSize, totalItems);
        }
        public ApiResponse SchemeAdd(AddAssessSchemeRequest request, int userid)
        {
            var categorydata = perforPerAssessCategoryRepository.GetEntity(w => w.Id == request.CategoryId);
            if (categorydata == null)
                throw new PerformanceException("当前考核类别不存在");
            var schemeData = perforPerAssessSchemeRepository.GetEntities();
            var temp = schemeData.FirstOrDefault(w => w.AllotId == categorydata.AllotId && w.SchemeName == request.SchemeName);
            if (temp != null)
                throw new PerformanceException("当前考核方案已存在");
            //查询最大编号或赋初始值
            int codeMax = 0;
            if (schemeData.Any())
                int.TryParse(schemeData.Max(w => w.SchemeCode.Substring(1)), out codeMax);
            string schemeCode = codeMax <= 101009 ? $"B{101010}" : $"B{codeMax + 1}";
            var dateTime = DateTime.Now;
            var per_assess_scheme = new per_assess_scheme()
            {
                AllotId = categorydata.AllotId,
                AssessId = request.CategoryId,
                SchemeCode = schemeCode,
                SchemeName = request.SchemeName,
                SchemeRemarks = request.SchemeRemarks,
                CreateBy = userid,
                CreateTime = dateTime,
                UpdateBy = userid,
                UpdateTime = dateTime,
            };
            if (perforPerAssessSchemeRepository.Add(per_assess_scheme))
                return new ApiResponse(ResponseType.OK, "添加成功");
            else return new ApiResponse(ResponseType.Fail, "添加失败");
        }
        public ApiResponse<UpdateAssessSchemeRequest> SchemeUpdate(UpdateAssessSchemeRequest request, int userid)
        {
            var categorydata = perforPerAssessCategoryRepository.GetEntity(w => w.Id == request.CategoryId);
            if (categorydata == null)
                throw new PerformanceException("当前考核类别不存在");
            var any = perforPerAssessSchemeRepository.GetEntity(w => w.Id == request.SchemeId);
            any.AssessId = request.CategoryId;
            any.SchemeName = request.SchemeName;
            any.SchemeRemarks = request.SchemeRemarks;
            any.UpdateBy = userid;
            any.UpdateTime = DateTime.Now;
            if (perforPerAssessSchemeRepository.Update(any)) return new ApiResponse<UpdateAssessSchemeRequest>(ResponseType.OK, "修改成功");
            else return new ApiResponse<UpdateAssessSchemeRequest>(ResponseType.Fail, "修改失败");
        }
        //考核方案删除(允许批量删除，删除时要检查有没有外表引用，提示一起删除)
        public ApiResponse SchemeDelete(BatchAssessSchemeRequest request)
        {
            var temp = perforPerAssessSchemeItemsRepository.GetEntity(w => request.SchemeId.Contains(w.SchemeId));
            if (temp != null || temp?.Id > 0)
                throw new PerformanceException("请先删除方案下的考核内容");
            var temp1 = perforPerAssessSchemeTargetRepository.GetEntity(w => request.SchemeId.Contains(w.SchemeId));
            if (temp1 != null || temp1?.Id > 0)
                throw new PerformanceException("请先删除方案下的核算单元");
            var issuedates = perforPerAssessSchemeRepository.GetEntities(w => request.SchemeId.Contains(w.Id)).ToList();
            if (perforPerAssessSchemeRepository.RemoveRange(issuedates.ToArray())) return new ApiResponse(ResponseType.OK, "删除成功");
            else return new ApiResponse(ResponseType.Fail, "删除失败");
        }

        public string ExcelDownload(List<Dictionary<string, object>> rows, string name, List<ExcelDownloadHeads> headList)
        {
            var data = new List<Dictionary<string, object>>();
            foreach (var obj in rows)
            {
                Dictionary<string, object> nobj = new Dictionary<string, object>();
                foreach (var item in obj)
                {
                    var lower = item.Key.ToLower();
                    if (lower.Contains("etime"))
                        nobj[lower] = Convert.ToDateTime(item.Value).ToString("d");
                    else if (lower.Contains("results"))
                    {
                        var detRows = JsonConvert.DeserializeObject<List<Dictionary<string, object>>>(item.Value.ToString());
                        foreach (var detlist in detRows)
                        {
                            object value = null;
                            foreach (var detitem in detlist)
                            {
                                if (detitem.Key.Equals("Value", StringComparison.OrdinalIgnoreCase))
                                    value = detitem.Value;
                                if (detitem.Key.Equals("Title", StringComparison.OrdinalIgnoreCase))
                                    nobj[detitem.Value.ToString()] = value;
                            }
                        }
                    }
                    else nobj[lower] = item.Value;
                }
                data.Add(nobj);
            }
            var dpath = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "Files");
            if (!Directory.Exists(dpath)) Directory.CreateDirectory(dpath);

            string filepath = Path.Combine(dpath, $"{name}{DateTime.Now:yyyy年MM月dd日}");
            if (File.Exists(filepath)) File.Delete(filepath);

            using (FileStream fs = new FileStream(filepath, FileMode.OpenOrCreate))
            using (ExcelPackage package = new ExcelPackage(fs))
            {
                var worksheet = package.Workbook.Worksheets.Add(name);
                for (int col = 0; col < headList.Count; col++)
                {
                    worksheet.SetValue(1, col + 1, headList[col].Alias);
                }
                for (int col = 0; col < headList.Count; col++)
                {
                    for (int row = 0; row < data.Count(); row++)
                    {
                        var temp = data.ElementAt(row);
                        var low = temp.Keys.ToString().ToLower();
                        var value = temp.GetValue(headList[col].Name, "");

                        worksheet.Cells[row + 2, col + 1].Value = value;
                    }
                }
                #region 样式设置
                for (int row = worksheet.Dimension.Start.Row; row <= worksheet.Dimension.End.Row; row++)
                {
                    worksheet.Row(row).Height = 20;
                    for (int col = worksheet.Dimension.Start.Column; col <= worksheet.Dimension.End.Column; col++)
                    {
                        worksheet.Cells[row, col].Style.Border.BorderAround(ExcelBorderStyle.Thin);
                        worksheet.Cells[row, col].Style.VerticalAlignment = ExcelVerticalAlignment.Center;
                        worksheet.Cells[row, col].Style.HorizontalAlignment = ExcelHorizontalAlignment.Center;
                    }
                }
                worksheet.Cells[1, 1, 1, headList.Count].Style.Font.Bold = true;
                worksheet.View.FreezePanes(1, 1);
                worksheet.Cells.AutoFitColumns();
                for (int col = worksheet.Dimension.Start.Column; col <= worksheet.Dimension.End.Column; col++)
                {
                    worksheet.Column(col).Width = worksheet.Column(col).Width > 20 ? 20 : worksheet.Column(col).Width;
                }
                #endregion
                package.Save();
            }
            return filepath;
        }
        #endregion
        #region 考核指标
        // 考核指标项列表
        public PagedList<per_assess_scheme_items> SchemeItemsList(QuerySchemeItemsList query)
        {
            var result = perforPerAssessSchemeItemsRepository.GetEntities(t => t.SchemeId == query.SchemeId && t.AllotId == query.AllotId).OrderByDescending(w => w.UpdateTime).ToList();
            result = result.Where(w => (string.IsNullOrEmpty(query.UnitType) || w.UnitType.Contains(query.UnitType))
                                       && (string.IsNullOrEmpty(query.AccountingUnit) || w.AccountingUnit.Contains(query.AccountingUnit))
                                       && (string.IsNullOrEmpty(query.ItemName2) || w.ItemName2.Contains(query.ItemName2))).ToList();
            var totalItems = result.Count();
            var pagedIssueSchemes = result.Skip((query.Page - 1) * query.PageSize).Take(query.PageSize).ToList();
            return new PagedList<per_assess_scheme_items>(pagedIssueSchemes, query.Page, query.PageSize, totalItems);
        }
        // 考核指标项新增
        public ApiResponse<AddAssessSchemeItemsRequest> SchemeItemsAdd(AddAssessSchemeItemsRequest request, int userid)
        {
            var cofAccounting = cofaccountingRepository.GetEntity(w => w.AllotId == request.AllotId && w.AccountingUnit == request.AccountingUnit && w.UnitType == request.UnitType);
            if (cofAccounting == null)
                throw new PerformanceException("当前的核算组别或者核算单元错误");
            var scheme = perforPerAssessSchemeRepository.GetEntities().FirstOrDefault(w => w.Id == request.SchemeId && w.AllotId == request.AllotId);
            if (scheme == null)
                throw new PerformanceException("当前考核方案有误，请刷新！");
            var categoryData = perforPerAssessSchemeItemsRepository.GetEntities();
            var temp = categoryData.FirstOrDefault(w => w.SchemeId == request.SchemeId && w.ItemName2 == request.ItemName2);
            if (temp != null)
                throw new PerformanceException("当前指标已存在");
            int codeMax = 0;
            if (categoryData.Any())
                int.TryParse(categoryData.Max(w => w.ItemCode.Substring(1)), out codeMax);
            string code = codeMax <= 1009 ? $"C{1010}" : $"C{codeMax + 1}";
            var dateTime = DateTime.Now;
            var data = mapper.Map<per_assess_scheme_items>(request);
            data.AllotId = request.AllotId;
            data.AssessId = scheme.AssessId;
            data.ItemCode = code;
            data.UnitCode = cofAccounting.Code;
            data.CreateBy = userid;
            data.CreateTime = dateTime;
            data.UpdateBy = userid;
            data.UpdateTime = dateTime;
            if (perforPerAssessSchemeItemsRepository.Add(data)) return new ApiResponse<AddAssessSchemeItemsRequest>(ResponseType.OK, "添加成功");
            else return new ApiResponse<AddAssessSchemeItemsRequest>(ResponseType.Fail, "添加失败");
        }
        // 考核指标项修改
        public ApiResponse<UpdateAssessSchemeItemsRequest> SchemeItemsUpdate(UpdateAssessSchemeItemsRequest request, int userid)
        {
            var cofAccounting = cofaccountingRepository.GetEntity(w => w.AllotId == request.AllotId && w.AccountingUnit == request.AccountingUnit && w.UnitType == request.UnitType);
            if (cofAccounting == null)
                throw new PerformanceException("当前的核算组别或者核算单元错误");
            var any = perforPerAssessSchemeItemsRepository.GetEntity(w => w.AllotId == request.AllotId && w.Id == request.SchemeItemsId);
            any.ItemName1 = request.ItemName1;
            any.ItemName2 = request.ItemName2;
            any.AssessScore = request.AssessScore;
            any.AssessNorm = request.AssessNorm;
            any.UnitCode = cofAccounting.Code;
            any.UnitType = request.UnitType;
            any.AccountingUnit = request.AccountingUnit;
            any.UpdateBy = userid;
            any.UpdateTime = DateTime.Now;
            if (perforPerAssessSchemeItemsRepository.Update(any)) return new ApiResponse<UpdateAssessSchemeItemsRequest>(ResponseType.OK, "修改成功");
            else return new ApiResponse<UpdateAssessSchemeItemsRequest>(ResponseType.Fail, "修改失败");
        }
        // 考核指标项删除(允许批量删除，删除时要检查有没有外表引用，提示一起删除)
        public ApiResponse SchemeItemsDelete(BatchAssessSchemeItemsRequest request)
        {
            var issuedates = perforPerAssessSchemeItemsRepository.GetEntities(w => request.SchemeItemsId.Contains(w.Id)).ToList();
            if (perforPerAssessSchemeItemsRepository.RemoveRange(issuedates.ToArray())) return new ApiResponse(ResponseType.OK, "删除成功");
            else return new ApiResponse(ResponseType.Fail, "删除失败");
        }
        //考核对象核算单元列表清单
        public PagedList<AssessSchemeTargetResponse> SchemeItemsTargetList(QuerySchemeItemsTargetList query)
        {
            //查询全部的方案
            var schemes = perforPerAssessSchemeRepository.GetEntities(w => w.AllotId == query.AllotId);
            if (schemes == null || !schemes.Any())
                throw new PerformanceException("未找到方案");
            //查询方案的考核对象
            var schemeTargets = perforPerAssessSchemeTargetRepository.GetEntities(w => w.AssessId == query.AssessId && w.AllotId == query.AllotId);

            //查询当前方案的考核对象
            var currentTargers = schemeTargets.Where(w => w.SchemeId == query.SchemeId).ToList();
            ////查询其他方案的考核对象
            var otherTargers = schemeTargets.Where(w => w.SchemeId != query.SchemeId).ToList();
            //查询全部的核算单元
            var cofaccounting = cofaccountingRepository.GetEntities(w => w.AllotId == query.AllotId);
            if (cofaccounting.Count() == 0 || !cofaccounting.Any())
                throw new PerformanceException("暂无核算单元数据");
            var stateOrders = new int[] { (int)Assess.SchemeItemsTarget.未设置方案, (int)Assess.SchemeItemsTarget.已设置其他方案, (int)Assess.SchemeItemsTarget.已设置方案 };
            var result = new List<AssessSchemeTargetResponse>();
            foreach (var cof in cofaccounting)
            {
                var currentScheme = currentTargers.Where(w => w.AccountingUnit == cof.AccountingUnit && w.UnitType == cof.UnitType).FirstOrDefault();
                var otherScheme = otherTargers.Where(w => w.AccountingUnit == cof.AccountingUnit && w.UnitType == cof.UnitType).FirstOrDefault();
                var data = mapper.Map<AssessSchemeTargetResponse>(cof);
                if (currentScheme?.Id > 0)
                {
                    data.TargetId = currentScheme.Id;
                    data.SchemeId = currentScheme.SchemeId;
                    data.CreateBy = currentScheme.CreateBy;
                    data.CreateTime = currentScheme.CreateTime;
                    data.UpdateBy = currentScheme.UpdateBy;
                    data.UpdateTime = currentScheme.UpdateTime;
                    data.SchemeName = schemes.Where(w => w.Id == currentScheme.SchemeId).FirstOrDefault().SchemeName;
                    data.SchemeState = (int)Assess.SchemeItemsTarget.已设置方案;
                }
                else if (otherScheme?.Id > 0)
                {
                    data.TargetId = otherScheme.Id;
                    data.SchemeId = otherScheme.SchemeId;
                    data.SchemeName = schemes.Where(w => w.Id == otherScheme.SchemeId).FirstOrDefault().SchemeName;
                    data.SchemeState = (int)Assess.SchemeItemsTarget.已设置其他方案;
                }
                else
                {
                    data.SchemeName = "无";
                    data.SchemeState = (int)Assess.SchemeItemsTarget.未设置方案;
                }
                result.Add(data);
            }
            if ((int)query.SchemeItemsTarget == (int)Assess.SchemeItemsTarget.未设置方案)
                result = result.Where(w => w.SchemeState == (int)query.SchemeItemsTarget).ToList();
            if ((int)query.SchemeItemsTarget == (int)Assess.SchemeItemsTarget.已设置方案)
                result = result.Where(w => w.SchemeState == (int)Assess.SchemeItemsTarget.已设置方案).ToList();
            result = result.OrderBy(w => Array.IndexOf(stateOrders, w.SchemeState)).ToList();
            result = result.Where(w => (string.IsNullOrEmpty(query.UnitType) || w.UnitType.Contains(query.UnitType))
                           && (string.IsNullOrEmpty(query.AccountingUnit) || w.AccountingUnit.Contains(query.AccountingUnit))).ToList();
            var totalItems = result.Count();
            var pagedIssueSchemes = result.Skip((query.Page - 1) * query.PageSize).Take(query.PageSize).ToList();
            return new PagedList<AssessSchemeTargetResponse>(pagedIssueSchemes, query.Page, query.PageSize, totalItems);
        }
        // 考核对象核算单元保存
        public ApiResponse SchemeItemsTargetSave(TargetAssessSchemeItemsRequest request, int userid)
        {
            if (!request.SchemeTargetResponse.Any())
                throw new PerformanceException("当前没有需要添加或者修改的内容");

            var schemes = perforPerAssessSchemeRepository.GetEntity(w => w.Id == request.SchemeId);
            var dateTime = DateTime.Now;
            foreach (var item in request.SchemeTargetResponse)
            {
                var any = perforPerAssessSchemeTargetRepository.GetEntity(w => w.Id == item.TargetId);
                if (any != null || any?.Id > 0)
                {
                    any.AllotId = schemes.AllotId;
                    any.AssessId = schemes.AssessId;
                    any.SchemeId = request.SchemeId;
                    any.UpdateBy = userid;
                    any.UpdateTime = dateTime;
                    perforPerAssessSchemeTargetRepository.Update(any);
                }
                else
                {
                    var data = mapper.Map<per_assess_scheme_target>(item);
                    data.AllotId = schemes.AllotId;
                    data.AssessId = schemes.AssessId;
                    data.SchemeId = request.SchemeId;
                    data.UnitCode = item.Code;
                    data.CreateBy = userid;
                    data.CreateTime = dateTime;
                    data.UpdateBy = userid;
                    data.UpdateTime = dateTime;
                    perforPerAssessSchemeTargetRepository.Add(data);
                }
            }
            return new ApiResponse(ResponseType.OK);
        }

        public ApiResponse SchemeItemsTargetEdit(TargetSchemeItemsTargetEdit edit, int userid)
        {
            var cofAccounting = cofaccountingRepository.GetEntity(w => w.AllotId == edit.AllotId && w.UnitType == edit.UnitType && w.AccountingUnit == edit.AccountingUnit);
            if (cofAccounting == null)
                throw new PerformanceException("当前的核算组别或者核算单元错误");
            var schemeTarget = perforPerAssessSchemeTargetRepository.GetEntity(w => w.Id == edit.TargetId && w.AllotId == edit.AllotId);
            if (schemeTarget == null)
                throw new PerformanceException("考核对象未找到，请刷新后重试！");
            schemeTarget.UnitCode = cofAccounting.Code;
            schemeTarget.UnitType = cofAccounting.UnitType;
            schemeTarget.AccountingUnit = edit.AccountingUnit;
            schemeTarget.UpdateBy = userid;
            schemeTarget.UpdateTime = DateTime.Now;
            if (perforPerAssessSchemeTargetRepository.Update(schemeTarget)) return new ApiResponse(ResponseType.OK, "修改成功");
            else return new ApiResponse(ResponseType.Fail, "修改失败");
        }

        public ApiResponse SchemeItemsTargetDelete(TargetSchemeItemsTargetDelete delete)
        {
            var issuedates = perforPerAssessSchemeTargetRepository.GetEntities(w => delete.TargetId.Contains(w.Id)).ToList();
            if (perforPerAssessSchemeTargetRepository.RemoveRange(issuedates.ToArray())) return new ApiResponse(ResponseType.OK, "删除成功");
            else return new ApiResponse(ResponseType.Fail, "删除失败");
        }
        public ApiResponse SchemeItemsUpload(int schemeId, int allotId, IFormCollection form, int userid)
        {
            var file = ((FormFileCollection)form.Files).FirstOrDefault();
            if (!file.FileName.EndsWith(".xlsx"))
                throw new PerformanceException("请检查是否为xlsx格式");
            //查询全部的核算单元
            var cofaccountingdatas = cofaccountingRepository.GetEntities(w => w.AllotId == allotId);
            //查询指标
            var itemsDatas = perforPerAssessSchemeItemsRepository.GetEntities(t => t.SchemeId == schemeId);
            var allot = perforPerallotRepository.GetEntity(t => t.ID == allotId);
            if (allot == null)
                return new ApiResponse(ResponseType.Fail, "allotid不存在");
            var name = FileHelper.GetFileNameNoExtension(file.FileName) + DateTime.Now.ToString("yyyyMMddHHmmssfff");
            var ext = FileHelper.GetExtension(file.FileName);

            var dpath = Path.Combine(evn.ContentRootPath, "Files", $"{allot.HospitalId}", $"{allot.Year}{allot.Month.ToString().PadLeft(2, '0')}");
            FileHelper.CreateDirectory(dpath);
            var path = Path.Combine(dpath, $"{name}{ext}");
            using (var stream = file.OpenReadStream())
            {
                byte[] bytes = new byte[stream.Length];
                stream.Read(bytes, 0, bytes.Length);
                if (!FileHelper.CreateFile(path, bytes))
                    return new ApiResponse(ResponseType.Fail, $"{file.FileName}上传失败");
            }
            var dt = Read(path);
            var datas = ToListDictionary(dt);
            if (datas.Count == 0 || !datas.Any())
                throw new PerformanceException("未在文件中找到数据");
            Tables error = new Tables("行", "考核指标编码", "一级指标名称", "二级指标名称", "考核分值", "考核标准", "考核单元组别", "考核单元名称", "原因");
            var upload = new List<AssessSchemeItemsUploadResponse>();
            foreach (var item in datas.Select((value, i) => new { value, index = $"第{i + 1}行" }))
            {
                if (string.IsNullOrEmpty(string.Join("", item.value.Values))) continue;
                var eItemCode = item.value.GetOrAdd("考核指标编码", "")?.ToString() ?? "";
                var eItemName1 = item.value.GetOrAdd("一级指标名称", "")?.ToString() ?? "";
                var eItemName2 = item.value.GetOrAdd("二级指标名称", "")?.ToString() ?? "";
                var eAssessScore = item.value.GetOrAdd("考核分值", "")?.ToString() ?? "";
                var eAssessNorm = item.value.GetOrAdd("考核标准", "")?.ToString() ?? "";
                var eUnitType = item.value.GetOrAdd("考核单元组别", "")?.ToString() ?? "";
                var eAccountingUnit = item.value.GetOrAdd("考核单元名称", "")?.ToString() ?? "";
                eAssessScore = String.IsNullOrEmpty(eAssessScore) ? "0" : eAssessScore;
                error.AddIf(string.IsNullOrEmpty(eItemName1), item.index, "", eItemName1, eItemName2, eAssessScore, eAssessNorm, eAccountingUnit, "一级指标名称空值无效，请检查后重试！");
                error.AddIf(string.IsNullOrEmpty(eItemName2), item.index, "", eItemName1, eItemName2, eAssessScore, eAssessNorm, eAccountingUnit, "二级指标名称空值无效，请检查后重试！");
                error.AddIf(!decimal.TryParse(eAssessScore, out decimal eAScore), item.index, "", eItemName1, eItemName2, eAssessScore, eAssessNorm, eAccountingUnit, "考核分值填写无效，请检查后重试！");
                error.AddIf(eAScore == 0, item.index, "", eItemName1, eItemName2, eAssessScore, eAssessNorm, eAccountingUnit, "考核分值不能为0，请检查后重试！");
                error.AddIf(string.IsNullOrEmpty(eAssessNorm), item.index, "", eItemName1, eItemName2, eAssessScore, eAssessNorm, eAccountingUnit, "考核标准空值无效，请检查后重试！");
                error.AddIf(string.IsNullOrEmpty(eUnitType), item.index, "", eItemName1, eItemName2, eAssessScore, eAssessNorm, eAccountingUnit, "考核单元组别空值无效，请检查后重试！");
                error.AddIf(string.IsNullOrEmpty(eAccountingUnit), item.index, "", eItemName1, eItemName2, eAssessScore, eAssessNorm, eAccountingUnit, "考核单元名称空值无效，请检查后重试！");
                var cofaccountingdata = cofaccountingdatas.FirstOrDefault(w => w.AccountingUnit == eAccountingUnit && w.UnitType == eUnitType);
                error.AddIf(cofaccountingdata == null, item.index, "", eItemName1, eItemName2, eAssessScore, eAssessNorm, eAccountingUnit, "未找到相关考核单元组别或者考核单元名称，请检查后重试！");
                if (cofaccountingdata == null) continue;
                var itemsData = itemsDatas.FirstOrDefault(w => w.ItemCode == eItemCode);
                var data = new AssessSchemeItemsUploadResponse();
                if (itemsData == null || itemsData?.Id < 0)
                {
                    data = new AssessSchemeItemsUploadResponse()
                    {
                        ItemName1 = eItemName1,
                        ItemName2 = eItemName2,
                        AssessScore = eAScore,
                        AssessNorm = eAssessNorm,
                        UnitCode = cofaccountingdata.Code,
                        UnitType = eUnitType,
                        AccountingUnit = eAccountingUnit,
                        OperationType = (int)Attendance.OperationType.新增
                    };
                }
                else
                {
                    data = new AssessSchemeItemsUploadResponse()
                    {
                        ItemCode = itemsData.ItemCode,
                        ItemName1 = eItemName1,
                        ItemName2 = eItemName2,
                        AssessScore = eAScore,
                        AssessNorm = eAssessNorm,
                        UnitCode = cofaccountingdata.Code,
                        UnitType = eUnitType,
                        AccountingUnit = eAccountingUnit,
                        OperationType = (int)Attendance.OperationType.修改
                    };
                }
                upload.Add(data);
            }
            if (error.Any())
                return new ApiResponse(ResponseType.WarningTable, "操作被拒绝，详细请看更多信息", error);
            saveUploadResult(upload, schemeId, allotId, userid);
            return new ApiResponse(ResponseType.OK);
        }

        public ApiResponse saveUploadResult(List<AssessSchemeItemsUploadResponse> upload, int schemeId, int allotId, int userid)
        {
            var categoryData = perforPerAssessSchemeRepository.GetEntity(t => t.Id == schemeId);
            if (categoryData == null || categoryData.Id < 0)
                throw new PerformanceException("方案有误，请刷新重试！");
            var itemsDatas = perforPerAssessSchemeItemsRepository.GetEntities(w => w.AllotId == allotId);
            var dataDelete = itemsDatas.Where(t => t.SchemeId == schemeId);
            var dataAdds = upload.Where(w => w.OperationType == (int)Attendance.OperationType.新增).ToList();
            int sort = 0;
            dataAdds.ForEach(t =>
            {
                t.sort = sort++;
                int codeMax = 0;
                if (itemsDatas.Any())
                    int.TryParse(itemsDatas.Max(w => w.ItemCode.Substring(1)), out codeMax);
                string code = codeMax <= 1009 ? $"C{1010 + sort}" : $"C{codeMax + sort}";
                t.ItemCode = code;
            });
            var dataUpdates = upload.Where(w => w.OperationType == (int)Attendance.OperationType.修改).ToList();
            //删除
            var dataDeletes = from temp1 in dataDelete
                              join temp2 in dataUpdates
                              on temp1.ItemCode equals temp2.ItemCode into tempJoin
                              from temp2 in tempJoin.DefaultIfEmpty()
                              where temp2 == null
                              select temp1;
            var dateTime = DateTime.Now;
            if (dataAdds.Any())
            {
                var inserts = dataAdds.Select(item =>
                {
                    return new per_assess_scheme_items()
                    {
                        AllotId = allotId,
                        AssessId = categoryData.AssessId,
                        SchemeId = schemeId,
                        ItemCode = item.ItemCode,
                        ItemName1 = item.ItemName1,
                        ItemName2 = item.ItemName2,
                        AssessScore = item.AssessScore,
                        AssessNorm = item.AssessNorm,
                        UnitCode = item.UnitCode,
                        UnitType = item.UnitType,
                        AccountingUnit = item.AccountingUnit,
                        CreateBy = userid,
                        CreateTime = dateTime,
                        UpdateBy = userid,
                        UpdateTime = dateTime,
                    };
                }).ToList();
                perforPerAssessSchemeItemsRepository.AddRange(inserts.ToArray());
            }
            if (dataUpdates.Any())
            {
                List<per_assess_scheme_items> itemsdatas = new List<per_assess_scheme_items>();
                foreach (var item in dataUpdates)
                {
                    var itemsData = itemsDatas.FirstOrDefault(w => w.ItemCode == item.ItemCode);
                    if (itemsData == null) continue;
                    itemsData.ItemCode = item.ItemCode;
                    itemsData.ItemName1 = item.ItemName1;
                    itemsData.ItemName2 = item.ItemName2;
                    itemsData.AssessScore = item.AssessScore;
                    itemsData.AssessNorm = item.AssessNorm;
                    itemsData.UnitType = item.UnitType;
                    itemsData.AccountingUnit = item.AccountingUnit;
                    itemsData.UpdateBy = userid;
                    itemsData.UpdateTime = dateTime;
                    itemsdatas.Add(itemsData);
                }
                perforPerAssessSchemeItemsRepository.UpdateRange(itemsdatas.ToArray());
            }
            if (dataDeletes.Any())
            {
                perforPerAssessSchemeItemsRepository.RemoveRange(dataDeletes.ToArray());
            }
            return new ApiResponse(ResponseType.OK);
        }
        #endregion
        #region 核算单元上报考核结果
        public ApiResponse<List<AssessSchemeEnterListResponse>> SchemeEnterList(int allotId, int userid)
        {
            var issueSchemes = perforPerAssessIssueSchemeRepository.GetEntities(w => w.AllotId == allotId);
            //当角色对应时过滤
            var userInfo = _userRepository.GetUser(userid);
            if (userInfo?.User == null) throw new NotImplementedException("当前用户不存在");
            if (userInfo?.URole == null) throw new NotImplementedException("当前用户暂未分配角色");

            var unitTypes = UnitTypeUtil.GetMaps(userInfo?.URole.Type ?? 0);
            if (unitTypes?.Any() == true)
                issueSchemes = issueSchemes.Where(w => w.AccountingUnit == userInfo.User.Department && UnitTypeUtil.Is(w.UnitType, unitTypes)).ToList();
            var stateOrders = new int[] { (int)Assess.AssessState.待审核, (int)Assess.AssessState.驳回, (int)Assess.AssessState.审核通过, (int)Assess.AssessState.未提交 };
            var items = issueSchemes.GroupBy(w => new { w.AssessId, w.AssessCode, w.AssessName, w.AssessNorm, w.ItemId, w.ItemCode, w.ItemName2, w.UnitType, w.AccountingUnit })
                .Select(w => new AssessSchemeEnterListResponse
                {
                    AssessId = w.Key.AssessId,
                    AssessCode = w.Key.AssessCode,
                    AssessName = w.Key.AssessName,
                    AssessNorm = w.Key.AssessNorm,
                    UnitType = w.Key.UnitType,
                    AccountingUnit = w.Key.AccountingUnit,
                    ItemId = w.Key.ItemId,
                    ItemCode = w.Key.ItemCode,
                    ItemName2 = w.Key.ItemName2,
                    Count = w.Count(),
                    SubmitTime = w.OrderByDescending(o => o.SubmitTime).Select(s => s.SubmitTime).FirstOrDefault(),
                    AuditBy = w.OrderByDescending(o => o.AuditTime).Select(s => s.AuditBy).FirstOrDefault(),
                    AuditTime = w.OrderByDescending(o => o.AuditTime).Select(s => s.AuditTime).FirstOrDefault(),
                    ConfirmCount = w.Count(p => p.State == (int)Assess.AssessState.审核通过),
                    RejectCount = w.Count(p => p.State == (int)Assess.AssessState.驳回),
                    AwaitCount = w.Count(p => p.State == (int)Assess.AssessState.待审核),
                    AuditRemark = string.Join("；", w.Select(p => p.AuditRemark).Where(s => !string.IsNullOrEmpty(s)).Distinct()),
                }).ToList();

            foreach (var item in items)
            {
                item.State = (int)Assess.AssessState.未提交;
                if (item.AwaitCount > 0)
                    item.State = (int)Assess.AssessState.待审核;
                if (item.RejectCount > 0)
                    item.State = (int)Assess.AssessState.驳回;
                else if (item.ConfirmCount == item.Count)
                    item.State = (int)Assess.AssessState.审核通过;
            }
            items = items.OrderBy(w => stateOrders.Contains(w.State) ? Array.IndexOf(stateOrders, w.State) : int.MaxValue).ToList();
            return new ApiResponse<List<AssessSchemeEnterListResponse>>(ResponseType.OK, items);
        }
        public PagedList<AssessSchemeResultListResponse> SchemeResultList(QuerySchemeResultList query)
        {
            var allot = perforPerallotRepository.GetEntity(w => w.ID == query.AllotId);
            if (allot == null)
                throw new PerformanceException("当前绩效记录不存在");
            var viewAResult = perforPerallotRepository.GetAssessResult(query.AllotId);
            var viewAResultQuery = viewAResult.AsQueryable();
            if (query.SchemeId > 0)
                viewAResultQuery = viewAResultQuery.Where(w => w.SchemeId == query.SchemeId);
            if (!string.IsNullOrEmpty(query.TargetUnitType))
                viewAResultQuery = viewAResultQuery.Where(w => w.TargetUnitType == query.TargetUnitType);
            if (!string.IsNullOrEmpty(query.TargetAccountingUnit))
                viewAResultQuery = viewAResultQuery.Where(w => w.TargetAccountingUnit == query.TargetAccountingUnit);
            if (!string.IsNullOrEmpty(query.ItemName2))
                viewAResultQuery = viewAResultQuery.Where(w => w.ItemName2 == query.ItemName2);
            var result = viewAResultQuery.ToList();
            var data = result.Select(item =>
            {
                return new AssessSchemeResultListResponse()
                {
                    TargetUnitType = item.TargetUnitType,
                    TargetAccountingUnit = item.TargetAccountingUnit,
                    ItemName2 = item.ItemName2,
                    Score =  (item.Score==null?0: item.Score) + item.AssessScore,
                };
            }).ToList();


            var columns = data.Select(item => item.ItemName2).Distinct().ToList();
            var results = data.GroupBy(item => new { item.TargetUnitType, item.TargetAccountingUnit })
                .Select(t =>
                {
                    var dict = new Dictionary<string, object>
                    {
                        { "TargetUnitType" , t.Key.TargetUnitType },
                        { "TargetAccountingUnit" , t.Key.TargetAccountingUnit },
                    };
                    var newResultss = new List<AssessSchemeDictionaryResults>();
                    foreach (var column in columns)
                    {
                        var score = t.FirstOrDefault(w => w.ItemName2 == column).Score;
                        dict.Add(column, score);
                        var newResults = new AssessSchemeDictionaryResults()
                        {
                            Title = column,
                            Value = score
                        };
                        newResultss.Add(newResults);
                    }
                    var totalAssessScore = dict.Where(w => columns.Contains(w.Key)).Sum(w => (decimal?)w.Value);
                    dict.AddOrUpdate("TotalAssessScore", totalAssessScore);
                    return new AssessSchemeResultListResponse()
                    {
                        TargetUnitType = t.Key.TargetUnitType,
                        TargetAccountingUnit = t.Key.TargetAccountingUnit,
                        DictionaryResults = newResultss,
                        TotalAssessScore = totalAssessScore
                    };
                }).ToList();
            var totalItems = results.Count();
            var pagedIssueSchemes = results.Skip((query.Page - 1) * query.PageSize).Take(query.PageSize).ToList();
            return new PagedList<AssessSchemeResultListResponse>(pagedIssueSchemes, query.Page, query.PageSize, totalItems);
        }

        public PagedList<AssessSchemeEnterDetaiListResponse> SchemeEnterDetailList(QuerySchemeEnterDetailList query)
        {
            var issueSchemes = perforPerAssessIssueSchemeRepository.GetEntities(w => w.AllotId == query.AllotId);
            if (!issueSchemes.Any())
                throw new PerformanceException("暂无数据");
            var issueSchemesQuery = issueSchemes.AsQueryable();
            if (query.ItemId > 0)
                issueSchemesQuery = issueSchemesQuery.Where(w => w.ItemId == query.ItemId);
            if (!string.IsNullOrEmpty(query.TargetUnitType))
                issueSchemesQuery = issueSchemesQuery.Where(w => w.TargetUnitType == query.TargetUnitType);
            if (!string.IsNullOrEmpty(query.TargetAccountingUnit))
                issueSchemesQuery = issueSchemesQuery.Where(w => w.TargetAccountingUnit == query.TargetAccountingUnit);
            if (!string.IsNullOrEmpty(query.ItemName2))
                issueSchemesQuery = issueSchemesQuery.Where(w => w.ItemName2 == query.ItemName2);
            if ((int)query.State == (int)Assess.AssessState.审核通过)
                issueSchemesQuery = issueSchemesQuery.Where(w => w.State == (int)query.State);
            var result = issueSchemesQuery.ToList();
            var stateOrders = new int[] { (int)Assess.AssessState.待审核, (int)Assess.AssessState.驳回, (int)Assess.AssessState.审核通过, (int)Assess.AssessState.未提交 };

            var datas = mapper.Map<List<AssessSchemeEnterDetaiListResponse>>(result);
            datas = datas.OrderBy(w => stateOrders.Contains(w.State) ? Array.IndexOf(stateOrders, w.State) : int.MaxValue).ToList();
            var totalItems = datas.Count();
            var pagedIssueSchemes = datas.Skip((query.Page - 1) * query.PageSize).Take(query.PageSize).ToList();
            return new PagedList<AssessSchemeEnterDetaiListResponse>(pagedIssueSchemes, query.Page, query.PageSize, totalItems);
        }
        public ApiResponse SchemeEnterAudit(EditSchemeEnterAudit audit, string realName)
        {
            var issueSchemes = perforPerAssessIssueSchemeRepository.GetEntities(w => w.AllotId == audit.AllotId && w.ItemId == audit.ItemId);
            if (audit.IssueId > 0)
                issueSchemes = issueSchemes.Where(w => w.Id == audit.IssueId).ToList();
            var temp = issueSchemes.FirstOrDefault(w => w.State == (int)Assess.AssessState.未提交);
            if (temp != null || temp?.Id > 0)
                throw new PerformanceException("未提交的数据无法审核");
            var dateTime = DateTime.Now;
            foreach (var issueScheme in issueSchemes)
            {
                issueScheme.State = (int)audit.State;
                issueScheme.AuditRemark = audit.AuditRemark;
                issueScheme.AuditBy = realName;
                issueScheme.AuditTime = dateTime;
            }
            perforPerAssessIssueSchemeRepository.UpdateRange(issueSchemes.ToArray());
            return new ApiResponse(ResponseType.OK, "修改成功");
        }
        public ApiResponse SchemeEnterEdit(EditAssessSchemeEnterRequest request, int userid)
        {
            var issueSchemes = perforPerAssessIssueSchemeRepository.GetEntity(w => w.Id == request.IssueId);
            if (issueSchemes == null)
                throw new PerformanceException("未找到需要修改的数据，请刷新");
            issueSchemes.Score = request.Score;
            issueSchemes.ScoreRemark = request.ScoreRemark;
            issueSchemes.UpdateBy = userid;
            issueSchemes.State = (int)Assess.AssessState.未提交;
            issueSchemes.UpdateTime = DateTime.Now;

            if (perforPerAssessIssueSchemeRepository.Update(issueSchemes)) return new ApiResponse(ResponseType.OK, "修改成功");
            else return new ApiResponse(ResponseType.Fail, "修改失败");
        }
        public ApiResponse SchemeEnterSubmit(int allotId, int itemId, int userid)
        {
            var issueSchemes = perforPerAssessIssueSchemeRepository.GetEntities(w => w.AllotId == allotId && w.ItemId == itemId && w.State != (int)Assess.AssessState.审核通过);
            if (!issueSchemes.Any())
                throw new PerformanceException("未找到需要提交的数据，请稍后在试");
            var dateTime = DateTime.Now;
            foreach (var item in issueSchemes)
            {
                item.AuditBy = null;
                item.AuditTime = null;
                item.AuditRemark = null;
                item.State = (int)Assess.AssessState.待审核;
                item.SubmitBy = userid;
                item.SubmitTime = dateTime;
                item.UpdateBy = userid;
                item.UpdateTime = dateTime;
            }
            if (perforPerAssessIssueSchemeRepository.UpdateRange(issueSchemes.ToArray())) return new ApiResponse(ResponseType.OK, "修改成功");
            else return new ApiResponse(ResponseType.Fail, "修改失败");
        }

        public ApiResponse SchemeEnterUpload(int itemId, IFormCollection form, int userid)
        {
            var file = ((FormFileCollection)form.Files).FirstOrDefault();
            if (!file.FileName.EndsWith(".xlsx"))
                throw new PerformanceException("请检查是否为xlsx格式");

            //查询指标
            var itemsDatas = perforPerAssessSchemeItemsRepository.GetEntity(t => t.Id == itemId);
            if (itemsDatas == null || itemsDatas.Id < 0)
                throw new PerformanceException("上传失败，请刷新后重新上传！");
            //查询下发结果
            var issueDatas = perforPerAssessIssueSchemeRepository.GetEntities(w => w.ItemId == itemId);
            var allot = perforPerallotRepository.GetEntity(w => w.ID == itemsDatas.AllotId);
            if (allot == null)
                return new ApiResponse(ResponseType.Fail, "allotid不存在");
            var name = FileHelper.GetFileNameNoExtension(file.FileName) + DateTime.Now.ToString("yyyyMMddHHmmssfff");
            var ext = FileHelper.GetExtension(file.FileName);

            var dpath = Path.Combine(evn.ContentRootPath, "Files", $"{allot.HospitalId}", $"{allot.Year}{allot.Month.ToString().PadLeft(2, '0')}");
            FileHelper.CreateDirectory(dpath);
            var path = Path.Combine(dpath, $"{name}{ext}");
            using (var stream = file.OpenReadStream())
            {
                byte[] bytes = new byte[stream.Length];
                stream.Read(bytes, 0, bytes.Length);
                if (!FileHelper.CreateFile(path, bytes))
                    return new ApiResponse(ResponseType.Fail, $"{file.FileName}上传失败");
            }
            var dt = Read(path);
            var datas = ToListDictionary(dt);
            if (datas.Count == 0 || !datas.Any())
                throw new PerformanceException("未在文件中找到数据");
            Tables error = new Tables("行", "核算组别", "核算单元名称", "一级指标名称", "考核项目", "考核分值", "考核扣分", "扣分原因", "原因");
            var issues = new List<per_assess_issue_scheme>();
            foreach (var item in datas.Select((value, i) => new { value, index = $"第{i + 1}行" }))
            {
                if (string.IsNullOrEmpty(string.Join("", item.value.Values))) continue;
                var eTargetUnitType = item.value.GetOrAdd("核算组别", "")?.ToString() ?? "";
                var eTargetAccountingUnit = item.value.GetOrAdd("核算单元名称", "")?.ToString() ?? "";
                var eItemName1 = item.value.GetOrAdd("一级指标名称", "")?.ToString() ?? "";
                var eItemName2 = item.value.GetOrAdd("考核项目", "")?.ToString() ?? "";
                var eAssessScore = item.value.GetOrAdd("考核分值", "")?.ToString() ?? "";
                var eScore = item.value.GetOrAdd("考核扣分", "")?.ToString() ?? "";
                var eScoreRemark = item.value.GetOrAdd("扣分原因", "")?.ToString() ?? "";
                eScore = String.IsNullOrEmpty(eScore) ? "0" : eScore;
                eAssessScore = String.IsNullOrEmpty(eAssessScore) ? "0" : eAssessScore;
                decimal.TryParse(eAssessScore, out decimal eAScore);
                error.AddIf(string.IsNullOrEmpty(eTargetAccountingUnit), item.index, eTargetAccountingUnit, eTargetUnitType, eItemName1, eItemName2, eAssessScore, eScore, eScoreRemark, "核算单元空值无效，请检查后重试！");
                error.AddIf(string.IsNullOrEmpty(eTargetUnitType), item.index, eTargetAccountingUnit, eTargetUnitType, eItemName1, eItemName2, eAssessScore, eScore, eScoreRemark, "核算单元空值无效，请检查后重试！");
                error.AddIf(!decimal.TryParse(eScore, out decimal escore), item.index, eTargetAccountingUnit, eTargetUnitType, eItemName1, eItemName2, eAssessScore, eScore, eScoreRemark, "考核扣分值无效，请检查后重试！");
                error.AddIf(escore > eAScore, item.index, eTargetAccountingUnit, eTargetUnitType, eItemName1, eItemName2, eAssessScore, eScore, eScoreRemark, "考核扣分大于考核分值，请检查后重试！");

                var issueData = issueDatas.FirstOrDefault(w => w.ItemId == itemId && w.TargetAccountingUnit == eTargetAccountingUnit && w.TargetUnitType == eTargetUnitType);
                error.AddIf(issueData == null, item.index, eTargetAccountingUnit, eTargetUnitType, eItemName1, eItemName2, eAssessScore, eScore, eScoreRemark, "未找到部门，请检查后重试！");
                if (issueData == null) continue;
                issueData.Score = escore == 0 ? null : escore;
                issueData.ScoreRemark = eScoreRemark;
                issueData.UpdateBy = userid;
                issueData.UpdateTime = DateTime.Now;
                issues.Add(issueData);
            }
            if (error.Any())
                return new ApiResponse(ResponseType.WarningTable, "操作被拒绝，详细请看更多信息", error);
            if (issues.Any())
                perforPerAssessIssueSchemeRepository.UpdateRange(issues.ToArray());
            return new ApiResponse(ResponseType.OK);
        }
        #endregion
        public static DataTable Read(string path, int startRow = 1, int startCol = 1)
        {
            using ExcelPackage package = new ExcelPackage(new FileInfo(path));
            // 选择工作表
            ExcelWorksheet worksheet = package.Workbook.Worksheets[0];
            var dt = new DataTable(worksheet.Name);
            for (int i = startCol; i <= worksheet.Dimension.End.Column; i++)
            {
                dt.Columns.Add(worksheet.Cells[startRow, i].Value.ToString());
            }
            for (int i = startRow + 1; i <= worksheet.Dimension.End.Row; i++)
            {
                var row = dt.NewRow();
                for (int j = startCol; j <= worksheet.Dimension.End.Column; j++)
                {
                    row[j - startCol] = worksheet.Cells[i, j].Value;
                }
                dt.Rows.Add(row);
            }
            return dt;
        }
        public static List<Dictionary<string, object>> ToListDictionary(DataTable dt)
        {
            List<Dictionary<string, object>> list = new List<Dictionary<string, object>>();
            foreach (DataRow dr in dt.Rows)
            {
                Dictionary<string, object> dic = new Dictionary<string, object>();
                foreach (DataColumn dc in dt.Columns)
                {
                    dic.Add(dc.ColumnName, dr[dc.ColumnName]);
                }
                list.Add(dic);
            }
            return list;
        }

        /// <summary>
        /// 表格展示
        /// </summary>
        public class Tables : List<Dictionary<string, object>>
        {
            private readonly string[] Cols;
            /// ctor
            public Tables(params string[] cols)
            {
                if (cols.Length == 0)
                    throw new ArgumentNullException(nameof(cols));
                if (cols.Any(w => string.IsNullOrEmpty(w)))
                    throw new ArgumentException($"{nameof(cols)}存在空列名");
                if (cols.Distinct().Count() < cols.Length)
                    throw new ArgumentException($"{nameof(cols)}列名重复");

                Cols = cols;
            }
            /// <summary>
            /// 添加行
            /// </summary>
            /// <param name="values">需要和Colums保持个数一致</param>
            /// <exception cref="ArgumentNullException"></exception>
            public void Add(params string[] values)
            {
                var row = new Dictionary<string, object>();
                for (int i = 0; i < Cols.Length; i++)
                {
                    row.Add(Cols[i], values.Length > i ? values[i] : "");
                }
                Add(row);
            }
            /// <summary>
            /// 添加行
            /// </summary>
            /// <param name="right"></param>
            /// <param name="values">需要和Colums保持个数一致</param>
            /// <exception cref="ArgumentNullException"></exception>
            public void AddIf(bool right, params string[] values)
            {
                if (right)
                {
                    var row = new Dictionary<string, object>();
                    for (int i = 0; i < Cols.Length; i++)
                    {
                        row.Add(Cols[i], values.Length > i ? values[i] : "");
                    }
                    Add(row);
                }
            }
        }

    }

}
