using FluentValidation.AspNetCore;
using Microsoft.AspNetCore.Authorization;
using Microsoft.AspNetCore.Http;
using Microsoft.AspNetCore.Mvc;
using Performance.DtoModels;
using Performance.EntityModels;
using Performance.Services;
using Performance.Services.AllotCompute;
using System;
using System.Collections.Generic;
using System.Linq;
using System.Threading.Tasks;
using Performance.Infrastructure;
using Performance.DtoModels.Second;
using Microsoft.Extensions.Logging;

namespace Performance.Api.Controllers
{
    /// <summary>
    /// 二次绩效
    /// </summary>
    [ApiController]
    public class SecondAllotController : ControllerBase
    {
        private readonly ILogger<SecondAllotController> _logger;
        private readonly ClaimService claimService;
        private readonly AllotService _allotService;
        private readonly SecondAllotService secondAllotService;
        private readonly ResultComputeService resultComputeService;
        private readonly SecondAllotDetails secondAllotDetails;
        private readonly RedistributionService _redistributionService;

        public SecondAllotController(
            ILogger<SecondAllotController> logger,
            ClaimService claimService,
            AllotService allotService,
            SecondAllotService secondAllotService,
            ResultComputeService resultComputeService,
            SecondAllotDetails secondAllotDetails,
            RedistributionService redistributionService
            )
        {
            _logger = logger;
            this.claimService = claimService;
            _allotService = allotService;
            this.secondAllotService = secondAllotService;
            this.resultComputeService = resultComputeService;
            this.secondAllotDetails = secondAllotDetails;
            _redistributionService = redistributionService;
        }

        #region 二次绩效列表、录入数据展示，保存数据

        /// <summary>
        /// 二次绩效列表（没有需要初始化）
        /// </summary>
        /// <returns></returns>
        [Route("api/second/list")]
        [HttpPost]
        public ApiResponse List()
        {
            var userId = claimService.GetUserId();
            var result = secondAllotService.GetSecondList(userId);
            if (result != null && result.Any())
                result = result.OrderByDescending(t => t.Year).ThenByDescending(t => t.Month).ToList();
            return new ApiResponse(ResponseType.OK, result);
        }

        /// <summary>
        /// 二次绩效项目内容保存
        /// </summary>
        /// <returns></returns>
        [Route("api/second/savevalue/{secondid}")]
        [HttpPost]
        public ApiResponse SaveValue(int secondid, [FromBody] List<ag_fixatitem> request)
        {
            //if (secondid != 0 && (request == null || request.Count == 0))
            //    secondAllotService.DelValue(secondid, request);

            var allotCount = request.Where(t => t.AllotId > 0).Select(t => t.AllotId).Distinct().Count();
            if (allotCount != 1 || request.Any(t => t.AllotId == 0))
                throw new PerformanceException("一次绩效ID错误");

            var secondCount = request.Where(t => t.SecondId > 0).Select(t => t.SecondId).Distinct().Count();
            if (secondCount != 1 || request.Any(t => t.SecondId == 0))
                throw new PerformanceException("二次绩效ID错误");

            var typeCount = request.Where(t => t.Type > 0).Select(t => t.Type).Distinct().Count();
            if (request.Any(t => t.Type == 0)) //typeCount != 1 ||
                throw new PerformanceException("二次绩效项位置错误");

            var unitTypeCount = request.Where(t => !string.IsNullOrEmpty(t.UnitType)).Select(t => t.UnitType).Distinct().Count();
            if (unitTypeCount != 1 || request.Any(t => string.IsNullOrEmpty(t.UnitType)))
                throw new PerformanceException("科室类型错误");

            var repetition = request.Where(t => !string.IsNullOrWhiteSpace(t.ItemName))
                .GroupBy(t => new { t.RowNumber, t.ItemName /*, WorkType = t.WorkType ?? 0*/ }).Where(t => t.Count() > 1);
            if (repetition.Any())
                throw new PerformanceException(string.Join(";", repetition.Select(t => $"行{t.Key.RowNumber}项‘{t.Key.ItemName}’重复录入")));

            var result = secondAllotService.SaveValue(request, secondid);
            return new ApiResponse(ResponseType.OK);
        }

        /// <summary>
        /// 提交二次绩效分配结果
        /// </summary>
        /// <returns></returns>
        [Route("api/second/savecompute")]
        [HttpPost]
        public ApiResponse SaveCompute([FromBody] List<ag_compute> request)
        {
            var allotCount = request.Where(t => t.AllotId > 0).Select(t => t.AllotId).Distinct().Count();
            if (allotCount != 1 || request.Any(t => t.AllotId == 0))
                throw new PerformanceException("一次绩效ID错误");

            var secondCount = request.Where(t => t.SecondId > 0).Select(t => t.SecondId).Distinct().Count();
            if (secondCount != 1 || request.Any(t => t.SecondId == 0))
                throw new PerformanceException("二次绩效ID错误");

            var departmentCount = request.Where(t => !string.IsNullOrEmpty(t.Department)).Select(t => t.Department).Distinct().Count();
            if (departmentCount != 1 || request.Any(t => string.IsNullOrEmpty(t.Department)))
                throw new PerformanceException("科室名称错误");

            var personNameCount = request.Where(t => !string.IsNullOrEmpty(t.PersonName)).Select(t => t.PersonName).Distinct().Count();
            if (personNameCount != 1 || request.Any(t => string.IsNullOrEmpty(t.PersonName)))
                throw new PerformanceException("人员名称错误");

            var result = secondAllotService.SaveCompute(request);
            return new ApiResponse(ResponseType.OK);
        }

        /// <summary>
        /// 二次绩效录入页面配置信息
        /// </summary>
        /// <returns></returns>
        [Route("api/second/detail")]
        [HttpPost]
        public ApiResponse SecondDetail([CustomizeValidator(RuleSet = "Refresh"), FromBody] UseTempRequest request)
        {
            //var result = secondAllotService.GetSecondDetail(request, claimService.GetUserId());
            var result = secondAllotDetails.GetSecondDetails(claimService.GetUserId(), request.SecondId, request.HospitalId, request.IsArchive, request.EmployeeSource);
            return new ApiResponse(ResponseType.OK, result);
        }

        ///// <summary>
        ///// 二次绩效录入页面配置信息
        ///// </summary>
        ///// <returns></returns>
        //[Route("api/second/otherdetail/{secondid}")]
        //[HttpPost]
        //public ApiResponse SecondOtherDetail(int secondid)
        //{
        //    var result = secondAllotService.GetSecondDetail(secondid);
        //    return new ApiResponse(ResponseType.OK, result);
        //}

        #endregion 二次绩效列表、录入数据展示，保存数据

        /// <summary>
        /// 二次绩效录入页面自动补全
        /// </summary>
        /// <returns></returns>
        [Route("api/second/autocomplete")]
        [HttpPost]
        public ApiResponse AutoComplete([FromBody] SecondEmpRequest request)
        {
            var result = secondAllotService.AutoComplete(request, claimService.GetUserId());
            //var result = secondAllotService.AutoComplete(request.SecondId, request.JobNumber);
            return new ApiResponse(ResponseType.OK, result);
        }

        /// <summary>
        /// 二次绩效录入页面其他模板自动补全
        /// </summary>
        /// <returns></returns>
        [Route("api/second/other/autocomplete")]
        [HttpPost]
        public ApiResponse OtherAutoComplete([FromBody] SecondEmpRequest request)
        {
            var result = secondAllotService.OtherAutoComplete(request, claimService.GetUserId());
            return new ApiResponse(ResponseType.OK, result);
        }

        #region 模板使用

        /// <summary>
        /// 选择二次绩效模板
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        [Route("api/temp/list")]
        public ApiResponse<List<SecondTempResponse>> Temp([FromBody] AllotDeptRequest request)
        {
            var userId = claimService.GetUserId();
            var result = secondAllotService.GetTemp(request.HospitalId, request.Department, userId);
            return new ApiResponse<List<SecondTempResponse>>(ResponseType.OK, result);
        }

        /// <summary>
        /// 保存已选择二次绩效模板
        /// </summary>
        /// <returns></returns>
        [Route("api/temp/usetemp")]
        [HttpPost]
        public ApiResponse UseTemp([CustomizeValidator(RuleSet = "Use"), FromBody] UseTempRequest request)
        {
            var result = secondAllotService.UseTemp(request);
            return result ? new ApiResponse(ResponseType.OK, "选择成功") : new ApiResponse(ResponseType.Fail, "选择失败");
        }

        /// <summary>
        /// 刷新已选择模板
        /// </summary>
        /// <returns></returns>
        [Route("api/second/refreshtemp")]
        [HttpPost]
        public ApiResponse RefreshTemp([CustomizeValidator(RuleSet = "Refresh"), FromBody] UseTempRequest request)
        {
            secondAllotService.RefreshTemp(request);
            return new ApiResponse(ResponseType.OK);
        }

        #endregion 模板使用

        #region 二次绩效工作量配置

        /// <summary>
        /// 二次绩效工作量列表
        /// </summary>
        /// <returns></returns>
        [Route("api/second/workload/list")]
        [HttpPost]
        public ApiResponse WorkloadList([CustomizeValidator(RuleSet = "Query"), FromBody] WorkloadRequest request)
        {
            var result = secondAllotService.GetWorkloadList(request);
            return new ApiResponse(ResponseType.OK, result);
        }

        /// <summary>
        /// 二次绩效工作量新增
        /// </summary>
        /// <returns></returns>
        [Route("api/second/workload/add")]
        [HttpPost]
        public ApiResponse WorkloadAdd([CustomizeValidator(RuleSet = "Add"), FromBody] WorkloadRequest request)
        {
            var result = secondAllotService.WorkloadAdd(request);
            return new ApiResponse(result ? ResponseType.OK : ResponseType.Fail);
        }

        /// <summary>
        /// 二次绩效工作量修改
        /// </summary>
        /// <returns></returns>
        [Route("api/second/workload/update")]
        [HttpPost]
        public ApiResponse WorkloadUpdate([CustomizeValidator(RuleSet = "Update"), FromBody] WorkloadRequest request)
        {
            var result = secondAllotService.WorkloadUpdate(request);
            return new ApiResponse(result ? ResponseType.OK : ResponseType.Fail);
        }

        /// <summary>
        /// 二次绩效工作量删除
        /// </summary>
        /// <returns></returns>
        [Route("api/second/workload/delete")]
        [HttpPost]
        public ApiResponse WorkloadDelete([CustomizeValidator(RuleSet = "Delete"), FromBody] WorkloadRequest request)
        {
            var result = secondAllotService.WorkloadDelete(request.Id);
            return new ApiResponse(result ? ResponseType.OK : ResponseType.Fail);
        }

        /// <summary>
        /// 二次绩效单例奖励列表
        /// </summary>
        /// <returns></returns>
        [Route("api/second/single/list")]
        [HttpPost]
        public ApiResponse SingleAwards([FromBody] WorkloadRequest request)
        {
            var result = secondAllotService.GetSingleList(request);
            return new ApiResponse(ResponseType.OK, result);
        }

        /// <summary>
        /// 二次绩效工作量类型列表
        /// </summary>
        /// <returns></returns>
        [Route("api/second/worktype/list/{secondId}")]
        [HttpPost]
        public ApiResponse WorkTypeList([FromBody] WorkloadRequest request, int secondId)
        {
            var result = secondAllotService.WorkTypeList(request, secondId);
            return new ApiResponse(ResponseType.OK, result);
        }

        /// <summary>
        /// 获取二次分配 提取工作量带出字典
        /// </summary>
        /// <returns></returns>
        [Route("api/second/worktype/map/{secondId}")]
        [HttpPost]
        public ApiResponse WorkloadMap(int secondId)
        {
            var result = secondAllotService.WorkloadMap(secondId);
            return new ApiResponse(ResponseType.OK, result);
        }

        /// <summary>
        /// 保存二次绩效工作量类型
        /// </summary>
        /// <returns></returns>
        [Route("api/second/worktype/save/{secondId}")]
        [HttpPost]
        public ApiResponse SingleSave([FromBody] ag_workload_type request, int secondId)
        {
            if (request.HospitalId == 0)
                return new ApiResponse(ResponseType.ParameterError, "医院信息无效");
            if (string.IsNullOrEmpty(request.TypeName))
                return new ApiResponse(ResponseType.ParameterError, "填写参数无效");

            var result = secondAllotService.SaveWorkType(request, secondId);
            return new ApiResponse(ResponseType.OK, result);
        }

        /// <summary>
        /// 删除二次绩效工作量类型
        /// </summary>
        /// <returns></returns>
        [Route("api/second/worktype/delete")]
        [HttpPost]
        public ApiResponse SingleDelete([CustomizeValidator(RuleSet = "Delete"), FromBody] WorkloadRequest request)
        {
            var result = secondAllotService.DeleteWorkType(request);
            return result ? new ApiResponse(ResponseType.OK, "删除成功") : new ApiResponse(ResponseType.Fail, "删除失败");
        }

        #endregion 二次绩效工作量配置

        #region 二次绩效审核

        /// <summary>
        /// 提交审核
        /// </summary>
        /// <param name="request">二次绩效Id</param>
        /// <returns></returns>
        [HttpPost]
        [Route("/api/second/audit/submit")]
        public ApiResponse SubmitAudit(SubmitAuditRequest request)
        {
            var second = secondAllotService.GetSecondAllot(request.SecondId);
            if (second == null)
                return new ApiResponse(ResponseType.ParameterError, "二次绩效Id无效");
            if (second.Status == 3)
                return new ApiResponse(ResponseType.Fail, "该绩效已\"审核通过\",无需再次提交");

            var userid = claimService.GetUserId();
            var result = secondAllotService.AuditSubmit(second, userid);
            return result ? new ApiResponse(ResponseType.OK, "提交成功") : new ApiResponse(ResponseType.Fail, "提交失败");
        }

        /// <summary>
        /// 二次绩效审核列表
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        [Route("/api/second/audit/list")]
        public ApiResponse<List<ag_secondallot>> AuditList([FromBody] AllotDeptRequest request)
        {
            var list = secondAllotService.AuditList(request.AllotId);
            return new ApiResponse<List<ag_secondallot>>(ResponseType.OK, "审核列表", list);
        }

        /// <summary>
        /// 二次绩效审核结果;驳回、成功
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        [Route("/api/second/audit/result")]
        public ApiResponse AuditResult([FromBody] SecondAuditRequest request)
        {
            var userid = claimService.GetUserId();
            var result = secondAllotService.ConfirmAudit(userid, request);
            //if (request.IsPass == 1)
            //{
            //    resultComputeService.SaveSecondReserved(request.SecondId);
            //}
            return result ? new ApiResponse(ResponseType.OK, "操作成功") : new ApiResponse(ResponseType.Fail, "操作失败");
        }

        /// <summary>
        /// 护理部二次绩效审核列表
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        [Route("/api/second/audit/nursingdept/list")]
        public ApiResponse<List<ag_secondallot>> NursingDeptlist([FromBody] AllotDeptRequest request)
        {
            var list = secondAllotService.NursingDeptlist(request.AllotId);
            return new ApiResponse<List<ag_secondallot>>(ResponseType.OK, "审核列表", list);
        }

        /// <summary>
        /// 护理部二次绩效审核结果;驳回、成功
        /// </summary>
        /// <returns></returns>
        [HttpPost]
        [Route("/api/second/audit/nursingdept/result")]
        public ApiResponse NursingDeptAuditResult([FromBody] SecondAuditRequest request)
        {
            var userid = claimService.GetUserId();
            var result = secondAllotService.NursingDeptAudit(userid, request);
            return result ? new ApiResponse(ResponseType.OK, "操作成功") : new ApiResponse(ResponseType.Fail, "操作失败");
        }

        #endregion 二次绩效审核

        #region 二次绩效其他绩效

        /// <summary>
        /// 二次绩效其他绩效详情
        /// </summary>
        /// <returns></returns>
        [Route("api/second/other/list")]
        [HttpPost]
        public ApiResponse OtherList([FromBody] AgOtherRequest request)
        {
            var result = secondAllotDetails.GetOtherTempDetails(claimService.GetUserId(), request.SecondId, request.IsArchive, request.EmployeeSource);
            //var result = secondAllotDetails.GetOtherTempData(claimService.GetUserId(), request.SecondId, request.IsArchive, request.EmployeeSource, out decimal? realAmount);
            var obj = new
            {
                header = secondAllotService.OtherListHeader(request.SecondId, result?.Sum(t => t.RealAmount)),
                body = result,
            };
            return new ApiResponse(ResponseType.OK, obj);
        }

        /// <summary>
        /// 二次绩效其他绩效保存
        /// </summary>
        /// <returns></returns>
        [Route("api/second/other/save")]
        [HttpPost]
        public ApiResponse OtherSave([FromBody] AgOtherRequest request)
        {
            var result = secondAllotService.OtherSave(request.SecondId, request.Othersources);
            return new ApiResponse(ResponseType.OK, result);
        }

        /// <summary>
        /// 二次绩效其他绩效保存(new)
        /// </summary>
        /// <param name="secondId"></param>
        /// <param name="request"></param>
        /// <returns></returns>
        [Route("api/second/other/save/{secondId}")]
        [HttpPost]
        public ApiResponse OtherSave(int secondId, [FromBody] SaveCollectData request)
        {
            secondAllotService.OtherSave(secondId, request);
            return new ApiResponse(ResponseType.OK);
        }

        #endregion 二次绩效其他绩效

        /// <summary>
        /// 二次绩效结果打印
        /// </summary>
        /// <returns></returns>
        [Route("api/second/print/{secondid}")]
        [HttpPost]
        public ApiResponse SecondPrint(int secondid)
        {
            var result = secondAllotService.Print(secondid);
            return new ApiResponse(ResponseType.OK, result);
        }

        /// <summary>
        /// 科主任/护士长绩效发布
        /// </summary>
        /// <returns></returns>
        [Route("api/second/deptcompute/{allotId}")]
        [HttpPost]
        public ApiResponse DeptComputeDetail(int allotId)
        {
            var userId = claimService.GetUserId();
            //var data = secondAllotService.DeptComputeDetail(userId, allotId, out int isShowManage);
            var data = secondAllotService.DeptComputeDetailList(userId, allotId, out int isShowManage);
            return new ApiResponse(ResponseType.OK, new { isShowManage, data });
        }

        /// <summary>
        /// 获取二次绩效详情数据
        /// </summary>
        /// <param name="secondId"></param>
        /// <param name="employeeSource"></param>
        /// <returns></returns>
        [HttpPost("api/second/detail/{secondId}/{employeeSource}")]
        public ApiResponse GetSecondAllotDetail([FromRoute] int secondId, int employeeSource)
        {
            var detail = secondAllotService.GetSecondSavedData(claimService.GetUserId(), secondId, employeeSource);
            return new ApiResponse(ResponseType.OK, detail);
        }

        /// <summary>
        /// 获取工作量类型
        /// </summary>
        /// <param name="secondId"></param>
        /// <returns></returns>
        [HttpPost("api/second/worktype/{secondId}")]
        public ApiResponse GetWorktypeDict([FromRoute] int secondId)
        {
            var detail = secondAllotService.GetWorkTypeDict(secondId);
            return new ApiResponse(ResponseType.OK, detail);
        }

        /// <summary>
        /// 获取工作量明细项
        /// </summary>
        /// <param name="secondId"></param>
        /// <returns></returns>
        [HttpPost("api/second/workload/{secondId}")]
        public ApiResponse GetWorkloadDict([FromRoute] int secondId)
        {
            var detail = secondAllotService.GetWorkloadDict(secondId);
            return new ApiResponse(ResponseType.OK, detail);
        }

        /// <summary>
        /// 二次绩效项目内容保存
        /// </summary>
        /// <param name="secondId"></param>
        /// <param name="request"></param>
        /// <returns></returns>
        [HttpPost("api/second/savedata/{secondId}")]
        [AllowAnonymous]
        public ApiResponse SaveValue([FromRoute] int secondId, [FromBody] dynamic request)
        {
            secondAllotService.SaveSecondAllotData(secondId, request);
            return new ApiResponse(ResponseType.OK);
        }

        /// <summary>
        /// 二次绩效录入页面自动补全
        /// </summary>
        /// <returns></returns>
        [Route("api/second/autocomplete/{secondId}")]
        [HttpPost]
        public ApiResponse AutoCompleteBodyData([FromRoute] int secondId, SecondEmployeeRequest request)
        {
            var result = secondAllotService.AutoComplete(secondId, request);
            return new ApiResponse(ResponseType.OK, result);
        }

        #region 二次分配后台计算
        /// <summary>
        /// 二次绩效录入页面
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        [Route("api/second/redistribution/load")]
        [HttpPost]
        public ApiResponse RedistributionLoad([FromBody] SecondLoadDto request)
        {
            try
            {
                if (!Enum.IsDefined(typeof(ComputeMode), request.ComputeMode))
                    throw new PerformanceException("暂不支持当前计算方式！");

                var overrideMode = EmployeeSource.Initial;
                if (Enum.IsDefined(typeof(EmployeeSource), request.OverrideMode))
                    overrideMode = (EmployeeSource)request.OverrideMode;

                var result = _redistributionService.Load(request.SecondId, (ComputeMode)request.ComputeMode, overrideMode);
                _redistributionService.ClearInvalidValue(result.Body?.Data);

                return new ApiResponse(ResponseType.OK, result);
            }
            catch (PerformanceException ex)
            {
                throw ex;
            }
            catch (Exception ex)
            {
                _logger.LogError($"二次绩效录入页面:{ex}");
                return new ApiResponse(ResponseType.Fail, "数据加载失败");
            }
        }


        /// <summary>
        /// 提交数据正确性检验
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        [Route("api/second/redistribution/check")]
        [HttpPost]
        public ApiResponse RedistributionCheck([FromBody] SecondComputeDto request)
        {
            try
            {
                if (request?.Body == null)
                    throw new PerformanceException("提交空参数，无法查看计算结果！");

                var second = secondAllotService.GetSecondAllot(request.SecondId);
                if (second == null) throw new PerformanceException("参数SecondId无效！");

                var allot = _allotService.GetAllot(second.AllotId.Value);
                if (allot == null)
                    throw new PerformanceException("绩效记录不存在！");
                // 年资职称绩效占比与工作量绩效占比 校验
                var loads = _redistributionService.GetWorkLoads(allot.HospitalId, second.UnitType, second.Department);
                if ((ComputeMode)request.ComputeMode != ComputeMode.NotCalculate)
                {
                    var workloadGroups = _redistributionService.GetTopWorkloadBodyGroups(loads);
                    var workloadRatio = workloadGroups.Select(w => request.Head.GetValue($"Workload_Ratio_{w.Name}", 0m));
                    if (workloadRatio.Any(w => w > 1 || w < 0))
                        throw new PerformanceException("工作量绩效占比存在异常值！");

                    var seniorityTitlesAccountedPerformance = request.Head.GetValue(nameof(ag_headsource.SeniorityTitlesAccountedPerformance), 0m);
                    if (seniorityTitlesAccountedPerformance > 1 || seniorityTitlesAccountedPerformance < 0)
                        throw new PerformanceException("年资职称绩效占比值异常！");

                    if (seniorityTitlesAccountedPerformance + workloadRatio.Sum() > 1)
                        throw new PerformanceException("年资职称绩效占比与工作量绩效占比总和，超过100%！");
                    else if (seniorityTitlesAccountedPerformance + workloadRatio.Sum() < 1)
                        throw new PerformanceException("年资职称绩效占比与工作量绩效占比总和，不足100%！");
                }
                // 二次分配人员信息 校验
                var result = _redistributionService.CheckData(second, (ComputeMode)request.ComputeMode, request.Body, loads);
                return new ApiResponse(ResponseType.OK, result);
            }
            catch (PerformanceException ex)
            {
                throw ex;
            }
            catch (Exception ex)
            {
                _logger.LogError($"提交数据正确性检验:{ex}");
                return new ApiResponse(ResponseType.Fail, "数据验证失败");
            }
        }

        /// <summary>
        /// 二次绩效结果计算
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        [Route("api/second/redistribution/compute")]
        [HttpPost]
        public ApiResponse RedistributionCompute([FromBody] SecondComputeDto request)
        {
            try
            {
                if (!Enum.IsDefined(typeof(ComputeMode), request.ComputeMode))
                    throw new PerformanceException("暂不支持当前计算方式！");

                if (request?.Body == null)
                    throw new PerformanceException("提交空参数，无法查看计算结果！");

                var second = secondAllotService.GetSecondAllot(request.SecondId);
                if (second == null) throw new PerformanceException("参数SecondId无效！");

                var allot = _allotService.GetAllot(second.AllotId.Value);
                if (allot == null)
                    throw new PerformanceException("绩效记录不存在！");
                // 年资职称绩效占比与工作量绩效占比 校验
                var loads = _redistributionService.GetWorkLoads(allot.HospitalId, second.UnitType, second.Department);
                var workloadGroups = _redistributionService.GetTopWorkloadBodyGroups(loads);

                if ((ComputeMode)request.ComputeMode != ComputeMode.NotCalculate)
                {
                    var workloadRatio = workloadGroups.Select(w => request.Head.GetValue($"Workload_Ratio_{w.Name}", 0m));
                    if (workloadRatio.Any(w => w > 1 || w < 0))
                        throw new PerformanceException("工作量绩效占比存在异常值！");

                    var seniorityTitlesAccountedPerformance = request.Head.GetValue(nameof(ag_headsource.SeniorityTitlesAccountedPerformance), 0m);
                    if (seniorityTitlesAccountedPerformance > 1 || seniorityTitlesAccountedPerformance < 0)
                        throw new PerformanceException("年资职称绩效占比值异常！");

                    if (seniorityTitlesAccountedPerformance + workloadRatio.Sum() > 1)
                        throw new PerformanceException("年资职称绩效占比与工作量绩效占比总和，超过100%！");
                    else if (seniorityTitlesAccountedPerformance + workloadRatio.Sum() < 1)
                        throw new PerformanceException("年资职称绩效占比与工作量绩效占比总和，不足100%！");
                }

                // 二次分配人员信息 校验
                var checkDatas = _redistributionService.CheckData(second, (ComputeMode)request.ComputeMode, request.Body, loads);
                if (checkDatas != null && checkDatas.Any(w => w.Level == ResponseType.Error.ToString()))
                    return new ApiResponse(ResponseType.Fail, "数据验证未通过，请修复后查看计算结果！", checkDatas.Where(w => w.Level == ResponseType.Error.ToString()));

                // 清理无效数据 没有Tab标签的数据才是要计算的数据
                var cleanDatas = request.Body.Where(w => w.Count > 0 && w.GetValue(nameof(ResponseType), "") == ResponseType.OK.ToString()).ToList();
                if (cleanDatas == null || cleanDatas.Count == 0)
                    throw new PerformanceException("提交参数都是无效数据，请重新填写数据后查看计算结果！");

                // 计算提交数据结果
                _redistributionService.ResultCompute((ComputeMode)request.ComputeMode, request.Head, cleanDatas, loads, workloadGroups);
                // 补充医院其他绩效
                _redistributionService.SupplementOtherPerfor(second, cleanDatas);
                // 重算部分数据
                _redistributionService.RedistributionCompute((ComputeMode)request.ComputeMode, request.Head, cleanDatas);

                _redistributionService.ClearInvalidValue(cleanDatas);
                var dic = _redistributionService.GetTableHeaderDictionary((ComputeMode)request.ComputeMode, allot, second, loads, workloadGroups);
                return new ApiResponse(ResponseType.OK, new { Head = request.Head, Body = cleanDatas, Dic = dic });
            }
            catch (PerformanceException ex)
            {
                throw ex;
            }
            catch (Exception ex)
            {
                _logger.LogError($"二次绩效结果计算:{ex}");
                return new ApiResponse(ResponseType.Fail, "计算失败");
            }
        }
        /// <summary>
        /// 二次绩效保存
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        [Route("api/second/redistribution/save")]
        [HttpPost]
        public ApiResponse RedistributionSave([FromBody] SecondComputeDto request)
        {
            try
            {
                var second = secondAllotService.GetSecondAllot(request.SecondId);
                if (second == null) throw new PerformanceException("参数SecondId无效！");

                var allot = _allotService.GetAllot(second.AllotId.Value);
                if (allot == null)
                    throw new PerformanceException("绩效记录不存在！");

                var loads = _redistributionService.GetWorkLoads(allot.HospitalId, second.UnitType, second.Department);
                // 二次分配人员信息 校验
                var checkDatas = _redistributionService.CheckData(second, (ComputeMode)request.ComputeMode, request.Body, loads);
                if (checkDatas != null && checkDatas.Any(w => w.Level == ResponseType.Error.ToString()))
                    return new ApiResponse(ResponseType.Fail, "数据验证未通过，请修复后查看计算结果！", checkDatas.Where(w => w.Level == ResponseType.Error.ToString()));

                // 清理无效数据 没有Tab标签的数据才是要计算的数据
                var cleanDatas = request.Body.Where(w => w.Count > 0 && w.GetValue(nameof(ResponseType), "") == ResponseType.OK.ToString()).ToList();
                if (cleanDatas == null || cleanDatas.Count == 0)
                    throw new PerformanceException("提交参数都是无效数据，请重新填写数据后保存！");

                var result = secondAllotService.RedistributionSave(allot, second, request.Head, cleanDatas);
                return result ? new ApiResponse(ResponseType.OK) : new ApiResponse(ResponseType.Fail, "保存失败");
            }
            catch (PerformanceException ex)
            {
                throw ex;
            }
            catch (Exception ex)
            {
                _logger.LogError($"二次绩效保存:{ex}");
                return new ApiResponse(ResponseType.Fail, "保存失败");
            }
        }

        /// <summary>
        /// 二次绩效提交
        /// </summary>
        /// <param name="request"></param>
        /// <returns></returns>
        [Route("api/second/redistribution/submit")]
        [HttpPost]
        public ApiResponse RedistributionSubmit([FromBody] SecondComputeDto request)
        {
            try
            {
                var second = secondAllotService.GetSecondAllot(request.SecondId);
                if (second == null)
                    return new ApiResponse(ResponseType.ParameterError, "二次绩效Id无效");
                if (second.Status == 3)
                    return new ApiResponse(ResponseType.Fail, "该绩效已\"审核通过\",无需再次提交");

                var allot = _allotService.GetAllot(second.AllotId.Value);
                if (allot == null)
                    throw new PerformanceException("绩效记录不存在！");

                if (!new int[] { (int)AllotStates.GenerateSucceed, (int)AllotStates.Archive }.Contains(allot.States))
                    throw new PerformanceException("绩效未下发，无法提交！");

                var loads = _redistributionService.GetWorkLoads(allot.HospitalId, second.UnitType, second.Department);
                // 二次分配人员信息 校验
                var checkDatas = _redistributionService.CheckData(second, (ComputeMode)request.ComputeMode, request.Body, loads);
                if (checkDatas != null && checkDatas.Any(w => w.Level == ResponseType.Error.ToString()))
                    return new ApiResponse(ResponseType.Fail, "数据验证未通过，请修复后查看计算结果！", checkDatas.Where(w => w.Level == ResponseType.Error.ToString()));

                // 清理无效数据 没有Tab标签的数据才是要计算的数据
                var cleanDatas = request.Body.Where(w => w.Count > 0 && w.GetValue(nameof(ResponseType), "") == ResponseType.OK.ToString()).ToList();
                if (cleanDatas == null || cleanDatas.Count == 0)
                    throw new PerformanceException("提交参数都是无效数据，请重新填写数据后查看计算结果！");

                var saveResult = secondAllotService.RedistributionSave(allot, second, request.Head, cleanDatas);
                if (saveResult)
                {
                    var userid = claimService.GetUserId();
                    var result = secondAllotService.AuditSubmit(second, userid);
                    if (result)
                        return new ApiResponse(ResponseType.OK, "提交成功");
                }
                return new ApiResponse(ResponseType.Fail, "提交失败");
            }
            catch (PerformanceException ex)
            {
                throw ex;
            }
            catch (Exception ex)
            {
                _logger.LogError($"二次绩效提交:{ex}");
                return new ApiResponse(ResponseType.Fail, "提交失败");
            }
        }
        /// <summary>
        /// 二次分配人员字典带出
        /// </summary> 
        /// <param name="request"></param>
        /// <returns></returns>
        [Route("api/second/redistribution/employee")]
        [HttpPost]
        public ApiResponse RedistributionEmployee([FromBody] SecondEmployeeDto request)
        {
            // 返回信息 
            var employees = _redistributionService.RedistributionEmployee(request);
            return new ApiResponse(ResponseType.OK, employees);
        }

        /// <summary>
        /// 二次分配审核后查看详情
        /// </summary> 
        /// <param name="request"></param>
        /// <returns></returns>
        [Route("api/second/redistribution/detail")]
        [HttpPost]
        public ApiResponse RedistributionDetail([FromBody] SecondBaseDto request)
        {
            if (!Enum.IsDefined(typeof(ComputeMode), request.ComputeMode))
                throw new PerformanceException("暂不支持当前计算方式！");

            var second = secondAllotService.GetSecondAllot(request.SecondId);
            if (second == null) throw new PerformanceException("参数SecondId无效！");

            var allot = _allotService.GetAllot(second.AllotId.Value);
            if (allot == null)
                throw new PerformanceException("绩效记录不存在！");
            // 年资职称绩效占比与工作量绩效占比 校验
            var loads = _redistributionService.GetWorkLoads(allot.HospitalId, second.UnitType, second.Department);
            var workloadGroups = _redistributionService.GetTopWorkloadBodyGroups(loads);

            // 返回信息 
            var (head, rows) = _redistributionService.RedistributionDetail((ComputeMode)request.ComputeMode, allot, second, workloadGroups);

            var dic = _redistributionService.GetTableHeaderDictionary((ComputeMode)request.ComputeMode, allot, second, loads, workloadGroups);
            return new ApiResponse(ResponseType.OK, new { Head = head, Body = rows, Dic = dic });
        }
        #endregion
    }
}
