using DotNetCore.CAP;
using FluentValidation;
using Hotline.Application.FlowEngine;
using Hotline.Configurations;
using Hotline.File;
using Hotline.FlowEngine.Workflows;
using Hotline.Orders;
using Hotline.Settings;
using Hotline.Settings.TimeLimitDomain;
using Hotline.Settings.TimeLimits;
using Hotline.Share.Dtos.FlowEngine.Workflow;
using Hotline.Share.Dtos.Order;
using Hotline.Share.Enums.FlowEngine;
using Hotline.Share.Enums.Order;
using Hotline.Share.Requests;
using Hotline.Validators.FlowEngine;
using MapsterMapper;
using Microsoft.Extensions.Options;
using SqlSugar;
using XF.Domain.Authentications;
using XF.Domain.Dependency;
using XF.Domain.Exceptions;
using XF.Domain.Repository;

namespace Hotline.Application.OrderApp
{
    public class OrderSecondaryHandlingApplication : IOrderSecondaryHandlingApplication, IScopeDependency
    {
        private readonly IMapper _mapper;
        private readonly IRepository<OrderSecondaryHandling> _orderSecondaryHandlingRepository;
        private readonly IFileRepository _fileRepository;
        private readonly IRepository<OrderVisit> _orderVisitRepository;
        private readonly ISessionContext _sessionContext;
        private readonly IOrderRepository _orderRepository;
        private readonly ITimeLimitDomainService _timeLimitDomainService;
        private readonly ICalcExpireTime _expireTime;
        private readonly ICapPublisher _capPublisher;
        private readonly IWorkflowApplication _workflowApplication;
        private readonly IRepository<OrderPublish> _orderPublishRepository;
        private readonly IRepository<OrderPublishHistory> _orderPublishHistoryRepository;
        private readonly IWorkflowDomainService _workflowDomainService;
        private readonly IRepository<OrderVisitDetail> _orderVisitedDetailRepository;
        private readonly IOrderDomainService _orderDomainService;
        private readonly IOrderScreenRepository _orderScreenRepository;
        private readonly IOptionsSnapshot<AppConfiguration> _appOptions;
        private readonly IOrderApplication _orderApplication;

        public OrderSecondaryHandlingApplication(
            IMapper mapper,
            IRepository<OrderSecondaryHandling> orderSecondaryHandlingRepository,
            IFileRepository fileRepository,
            IRepository<OrderVisit> orderVisitRepository,
            ISessionContext sessionContext,
            IOrderRepository orderRepository,
            ITimeLimitDomainService timeLimitDomainService,
            ICapPublisher capPublisher,
            IWorkflowApplication workflowApplication,
            IRepository<OrderPublish> orderPublishRepository,
            IRepository<OrderPublishHistory> orderPublishHistoryRepository,
            IWorkflowDomainService workflowDomainService,
            IRepository<OrderVisitDetail> orderVisitedDetailRepository,
            IOrderDomainService orderDomainService,
            IOrderScreenRepository orderScreenRepository,
            IOptionsSnapshot<AppConfiguration> appOptions,
            ICalcExpireTime expireTime,
            IOrderApplication orderApplication)
        {
            _mapper = mapper;
            _orderSecondaryHandlingRepository = orderSecondaryHandlingRepository;
            _fileRepository = fileRepository;
            _orderVisitRepository = orderVisitRepository;
            _sessionContext = sessionContext;
            _orderRepository = orderRepository;
            _timeLimitDomainService = timeLimitDomainService;
            _capPublisher = capPublisher;
            _workflowApplication = workflowApplication;
            _orderPublishRepository = orderPublishRepository;
            _orderPublishHistoryRepository = orderPublishHistoryRepository;
            _workflowDomainService = workflowDomainService;
            _orderVisitedDetailRepository = orderVisitedDetailRepository;
            _orderDomainService = orderDomainService;
            _expireTime = expireTime;
            _orderScreenRepository = orderScreenRepository;
            _appOptions = appOptions;
            _orderApplication = orderApplication;
        }

        /// <summary>
        ///  二次办理新增
        /// </summary>
        /// <returns></returns>
        public async Task AddAsync(AddOrderSecondaryHandlingDto dto, CancellationToken cancellationToken)
        {
            var model = _mapper.Map<OrderSecondaryHandling>(dto);
            if (string.IsNullOrEmpty(dto.Id))
            {
                model.InitId();
            }
            else
            {
                model = await _orderSecondaryHandlingRepository.GetAsync(dto.Id, cancellationToken);
                model.Content = dto.Content;
            }
            model.State = ESecondaryHandlingState.Apply;
            model.ApplyOrgId = _sessionContext.OrgId;
            model.ApplyOrgName = _sessionContext.OrgName;

            if (dto.Files.Any())
                model.FileJson = await _fileRepository.AddFileAsync(dto.Files, model.Id, "", cancellationToken);

            var visit = await _orderVisitRepository.GetAsync(x => x.Id == dto.VisitId && x.VisitState != EVisitState.None, cancellationToken);
            if (visit != null)
            {
                model.VisitState = visit.VisitState;
                //visit.VisitState = EVisitState.None;
                visit.IsCanHandle = false;
                await _orderVisitRepository.UpdateAsync(visit, cancellationToken);
            }

            if (!string.IsNullOrEmpty(dto.Id))
            {
                await _orderSecondaryHandlingRepository.UpdateAsync(model, cancellationToken);
            }
            else
            {
                await _orderSecondaryHandlingRepository.AddAsync(model, cancellationToken);
            }
        }

        public async Task SendBackAsync(SendBackOrderSecondaryHandlingDto dto, CancellationToken cancellationToken)
        {
            var model = await _orderSecondaryHandlingRepository.GetAsync(dto.Id, cancellationToken);
            model.State = ESecondaryHandlingState.NotApply;
            model.SendBackContent = dto.SendBackContent;
            model.AuditUser = _sessionContext.UserName;
            model.AuditTime = DateTime.Now;
            model.SendBackNum = model.SendBackNum is null ? 1 : model.SendBackNum + 1;
            await _orderSecondaryHandlingRepository.UpdateAsync(model, cancellationToken);
            var visit = await _orderVisitRepository.GetAsync(x => x.Id == model.VisitId, cancellationToken);
            if (visit != null)
            {
                //visit.VisitState = model.VisitState;
                visit.IsCanHandle = true;
                await _orderVisitRepository.UpdateAsync(visit, cancellationToken);
            }
        }


        /// <summary>
        /// 二次办理审批
        /// </summary>
        /// <returns></returns>
        public async Task AuditAsync(AuditOrderSecondaryHandlingDto dto, OrderSecondaryHandling model, CancellationToken cancellationToken)
        {
            model.State = dto.State;
            model.AuditContent = dto.AuditContent;
            model.AuditId = _sessionContext.UserId;
            model.AuditUser = _sessionContext.UserName;
            model.AuditTime = DateTime.Now;
            model.IsHandel = false;
            var visit = await _orderVisitRepository.GetAsync(x => x.OrderId == model.OrderId && x.VisitState == EVisitState.Visited, cancellationToken);
            if (model.State == ESecondaryHandlingState.End)
            {
                var order = await _orderRepository.GetAsync(x => x.Id == model.OrderId, cancellationToken);
                if (string.IsNullOrEmpty(order.WorkflowId))
                    throw UserFriendlyException.SameMessage("无效二次办理审批信息,没有找到对应流程信息！");
                string orgId = order.CounterSignType == ECounterSignType.Department ? model.ApplyOrgId.Substring(0, 6) : model.ApplyOrgId;
                var step = await _workflowDomainService.FindLastHandleStepAsync(order.WorkflowId, orgId, cancellationToken);
                if (step == null)
                    throw UserFriendlyException.SameMessage("无效二次办理审批信息,没有找到对应流程节点！");
                var recall = new RecallDto
                {
                    WorkflowId = order.WorkflowId!,
                    NextStepCode = step.Code,
                    NextStepName = step.Name,
                    NextHandlers = new List<StepAssignInfo> { step.GetWorkflowStepHandler() },
                    Opinion = dto.AuditContent,
                    FlowDirection = Share.Enums.FlowEngine.EFlowDirection.CenterToOrg,
                    HandlerType = step.HandlerType,
                    BusinessType = step.BusinessType
                };
                var reTransactNum = order.ReTransactNum is null ? 1 : order.ReTransactNum + 1;
                //var expiredTime = _timeLimitDomainService.CalcEndTime(DateTime.Now, order.AcceptTypeCode);

                var expiredTime = await _expireTime.CalcEndTime(DateTime.Now, DateTime.Now, order.AcceptTypeCode);
                var processType = step.FlowDirection == EFlowDirection.OrgToCenter || step.FlowDirection == EFlowDirection.CenterToCenter ? EProcessType.Zhiban : EProcessType.Jiaoban;
                var isOrderFiled = order.Status >= EOrderStatus.Filed;
                order.ExpiredTime = expiredTime.ExpiredTime;
                order.NearlyExpiredTime = expiredTime.NearlyExpiredTime;
                order.NearlyExpiredTimeOne = expiredTime.NearlyExpiredTimeOne;
                order.ReTransactNum = reTransactNum;
                order.ProcessType = processType;
                order.Status = EOrderStatus.Special;

                await _orderRepository.Updateable().SetColumns(o => new Order() { ExpiredTime = expiredTime.ExpiredTime, NearlyExpiredTime = expiredTime.NearlyExpiredTime, NearlyExpiredTimeOne = expiredTime.NearlyExpiredTimeOne, ReTransactNum = reTransactNum, ProcessType = processType, Status = EOrderStatus.Handling })
                    .Where(o => o.Id == order.Id).ExecuteCommandAsync(cancellationToken);
                var orderDto = _mapper.Map<OrderDto>(order);
                await _capPublisher.PublishAsync(Hotline.Share.Mq.EventNames.HotlineOrderExpiredTimeUpdate, orderDto, cancellationToken: cancellationToken);

                var publish = await _orderPublishRepository.GetAsync(x => x.OrderId == model.OrderId);
                if (publish != null)
                {
                    var publishHistory = _mapper.Map<OrderPublishHistory>(publish);
                    publishHistory.OrderPublishId = publish.Id;
                    publishHistory.ArrangeTitleAfter = publish.ArrangeTitle;
                    publishHistory.ArrangeTitleBefor = publish.ArrangeTitle;
                    publishHistory.ArrangeContentAfter = publish.ArrangeContent;
                    publishHistory.ArrangeContentBefor = publish.ArrangeContent;
                    publishHistory.ArrangeOpinionAfter = publish.ArrangeOpinion;
                    publishHistory.ArrangeOpinionBefor = publish.ArrangeOpinion;
                    await _orderPublishHistoryRepository.AddAsync(publishHistory, cancellationToken);
                    await _orderPublishRepository.RemoveAsync(publish, false, cancellationToken);
                }

                if (_appOptions.Value.IsYiBin)
                {
                    var screen = await _orderScreenRepository.Queryable().FirstAsync(
                    x => x.OrderId == model.OrderId &&
                         (x.Status != EScreenStatus.End && x.Status != EScreenStatus.Refuse), cancellationToken);
                    if (screen != null)
                    {
                        await _orderScreenRepository.RemoveAsync(screen, false, cancellationToken);
                    }
                }

                var (workflow, targetStepDefine, currentStep, targetStep, newStep, isOrgToCenter) = await _workflowDomainService.RecallAsync(recall,
                        recall.NextHandlers.FirstOrDefault(), EWorkflowTraceType.SecondHandle,
                        order.ExpiredTime, order.Status >= EOrderStatus.Filed, EHandleMode.SecondaryHandle,
                        (workflow, currentStep, targetStepDefine, targetStep, targetStepNew) =>
                        {
                            var basicWorkflowDto = _mapper.Map<BasicWorkflowDto>(dto);
                            var stepAssignInfo = _orderApplication.GetOrderRecallAssignInfoAsync(workflow, targetStepDefine, targetStep,
                                basicWorkflowDto, cancellationToken).Result; //todo 优化异步
                            if (stepAssignInfo is null) return;
                            var validator = new StepAssignInfoValidator();
                            validator.ValidateAndThrow(stepAssignInfo);
                            targetStepNew.Assign(stepAssignInfo);
                        },
                        cancellationToken);
                _mapper.Map(workflow, order);
                order.FileEmpty();
                await _orderRepository.UpdateAsync(order, false, cancellationToken);

                visit.VisitState = EVisitState.None;
            }
            else
            {
                visit.IsCanHandle = true;
            }
            await _orderVisitRepository.UpdateAsync(visit, cancellationToken);
            await _orderSecondaryHandlingRepository.UpdateAsync(model, cancellationToken);
        }


        /// <summary>
        /// 获取申请列表
        /// </summary>
        /// <returns></returns>
        public ISugarQueryable<OrderVisitDetail> ApplyQuery(MayScreenListDto dto, CancellationToken cancellationToken)
        {
            //dto.CreationTimeEnd = DateTime.Now;
            ////dto.CreationTimeStart = DateTime.Now;
            //dto.CreationTimeStart = _timeLimitDomainService.CalcWorkTimeReduce(DateTime.Now, 5);
            var isAdmin = _orderDomainService.IsCheckAdmin();
            var query = _orderVisitedDetailRepository.Queryable(false, true)
                .Includes(x => x.OrderVisit)
                .Includes(x => x.OrderVisit, y => y.Order)
                .Includes(x => x.OrderVisit, y => y.Employee)
                .Includes(x => x.SecondaryHandling)
                .Where(x => x.OrderVisit.Order.IsProvince == false)
                .LeftJoin<OrderScreen>((x, s) => x.Id == s.VisitDetailId && s.Status < EScreenStatus.End && s.IsDeleted == false)
                //.Where((x, s) => s.Id == null && (x.SecondaryHandling.State == ESecondaryHandlingState.NotApply || x.SecondaryHandling.Id == null))
                .Where(x => SqlFunc.Subqueryable<OrderSecondaryHandling>().Where(osh => osh.VisitDetailId == x.Id && osh.State != ESecondaryHandlingState.NotApply).NotAny())
                //.Where(x => x.OrderVisit.VisitTime < dto.CreationTimeEnd && x.OrderVisit.VisitTime > dto.CreationTimeStart)
                .WhereIF(!string.IsNullOrEmpty(dto.No), x => x.OrderVisit.Order!.No!.Contains(dto.No!))
                .WhereIF(dto.IsProvince.HasValue, x => x.OrderVisit.Order!.IsProvince == dto.IsProvince)
                .WhereIF(!string.IsNullOrEmpty(dto.Title), x => x.OrderVisit.Order!.Title!.Contains(dto.Title!))
                .WhereIF(!string.IsNullOrEmpty(dto.SourceChannel), x => x.OrderVisit.Order!.SourceChannelCode! == dto.SourceChannel!)
                .WhereIF(!string.IsNullOrEmpty(dto.AcceptType), x => x.OrderVisit.Order!.AcceptTypeCode! == dto.AcceptType!)
                .WhereIF(dto.CounterSignType.HasValue, x => x.OrderVisit.Order!.CounterSignType == dto.CounterSignType)
                .WhereIF(!string.IsNullOrEmpty(dto.OrgLevelOneName), x => x.OrderVisit.Order!.OrgLevelOneName!.Contains(dto.OrgLevelOneName!))
                .WhereIF(!string.IsNullOrEmpty(dto.CurrentHandleOrgName), x => x.OrderVisit.Order!.CurrentHandleOrgName!.Contains(dto.CurrentHandleOrgName!))
                .WhereIF(dto.CurrentHandleTime.HasValue && dto.EndCurrentHandleTime.HasValue, x => x.OrderVisit.Order!.ActualHandleTime >= dto.CurrentHandleTime && x.OrderVisit.Order!.ActualHandleTime <= dto.EndCurrentHandleTime)
                .WhereIF(dto.FiledTime.HasValue && dto.EndFiledTime.HasValue, x => x.OrderVisit.Order!.FiledTime >= dto.FiledTime && x.OrderVisit.Order!.FiledTime <= dto.EndFiledTime)
                .WhereIF(dto.CreationTime.HasValue && dto.EndCreationTime.HasValue, x => x.OrderVisit.Order!.CreationTime >= dto.CreationTime && x.OrderVisit.Order!.CreationTime <= dto.EndCreationTime)
                .WhereIF(dto.VisitTime.HasValue && dto.EndVisitTime.HasValue, x => x.OrderVisit.VisitTime >= dto.VisitTime && x.OrderVisit.VisitTime <= dto.EndVisitTime)
                .WhereIF(!string.IsNullOrEmpty(dto.VisitOrgName), x => x.VisitOrgName!.Contains(dto.VisitOrgName!))
                .WhereIF(!string.IsNullOrEmpty(dto.OrgProcessingResults), x => SqlFunc.JsonField(x.OrgProcessingResults, "Key") == dto.OrgProcessingResults)
                .WhereIF(!string.IsNullOrEmpty(dto.OrgHandledAttitude), x => SqlFunc.JsonListObjectAny(x.OrgHandledAttitude, "Key", dto.OrgHandledAttitude))
                .WhereIF(!string.IsNullOrEmpty(dto.OrgNoSatisfiedReason), x => SqlFunc.JsonField(x.OrgNoSatisfiedReason, "Key") == dto.OrgNoSatisfiedReason)
                //.Where(x => SqlFunc.Subqueryable<OrderVisit>().Where(ov => ov.Id == x.VisitId && ov.VisitState == EVisitState.Visited && ov.IsCanHandle).Any())
                .Where((x, s) => x.OrderVisit.VisitState == EVisitState.Visited && x.OrderVisit.IsCanHandle)
                .WhereIF(!isAdmin, (x, s) => (x.OrderVisit.Order.CounterSignType == ECounterSignType.Department || x.OrderVisit.Order.CounterSignType == null) && x.VisitOrgCode.StartsWith(_sessionContext.OrgId))
                ;
            if (_sessionContext.OrgId != null && !_sessionContext.OrgIsCenter)
            {
                query.WhereIF(!string.IsNullOrEmpty(dto.Keyword),
                        (x, s) => x.OrderVisit.Order.Title.Contains(dto.Keyword!) ||
                                  x.OrderVisit.Order.No.Contains(dto.Keyword!))
                    .Where((x, s) => x.VisitTarget == EVisitTarget.Org && x.VisitOrgCode.StartsWith(_sessionContext.OrgId) && (
                        SqlFunc.JsonField(x.OrgProcessingResults, "Key") == "1" ||
                        SqlFunc.JsonField(x.OrgProcessingResults, "Key") == "2"
                        || SqlFunc.JsonField(x.OrgHandledAttitude, "Key") == "1" ||
                        SqlFunc.JsonField(x.OrgHandledAttitude, "Key") == "2"
                    ));
            }
            else
            {
                query.WhereIF(!string.IsNullOrEmpty(dto.Keyword),
                        (x, s) => x.OrderVisit.Order.Title.Contains(dto.Keyword!) ||
                                  x.OrderVisit.Order.No.Contains(dto.Keyword!))
                    .Where((x, s) => x.VisitTarget == EVisitTarget.Org && (
                        SqlFunc.JsonField(x.OrgProcessingResults, "Key") == "1" ||
                        SqlFunc.JsonField(x.OrgProcessingResults, "Key") == "2"
                        || SqlFunc.JsonField(x.OrgHandledAttitude, "Key") == "1" ||
                        SqlFunc.JsonField(x.OrgHandledAttitude, "Key") == "2"
                    ));
            }

            return query.OrderByDescending((x, s) => x.CreationTime);
        }

        /// <summary>
        /// 二次办理列表查询
        /// </summary>
        /// <returns></returns>
        public ISugarQueryable<OrderSecondaryHandling> Query(SecondaryHandlingListDto dto, CancellationToken cancellationToken)
        {
            if (dto.CreationTimeEnd.HasValue)
                dto.CreationTimeEnd = dto.CreationTimeEnd.Value.AddDays(1).AddSeconds(-1);
            var quer = _orderSecondaryHandlingRepository.Queryable()
                .Includes(x => x.Order)
                .Includes(x => x.VisitDetail)
                .Includes(x => x.Visit, d => d.Order)
                .Where(x => x.State > ESecondaryHandlingState.NotApply)
                .WhereIF(!string.IsNullOrEmpty(dto.Keyword), x => x.Order.Title.Contains(dto.Keyword!) || x.Order.No.Contains(dto.Keyword!))
                .WhereIF(!string.IsNullOrEmpty(dto.No), x => x.Order.No.Contains(dto.No!))
                .WhereIF(!string.IsNullOrEmpty(dto.Channel), x => x.Order.SourceChannelCode == dto.Channel)              //来源渠道
                .WhereIF(dto.SendBack.HasValue && dto.SendBack == 1, x => x.SendBackNum == 1)                            //重提办理
                .WhereIF(dto.SendBack.HasValue && dto.SendBack != 1, x => x.SendBackNum == null)                            //重提办理
                .WhereIF(!string.IsNullOrEmpty(dto.Title), x => x.Order.Title.Contains(dto.Title!))                      //工单编号
                .WhereIF(!string.IsNullOrEmpty(dto.ApplyName), x => x.CreatorName.Contains(dto.ApplyName))               //申请人
                .WhereIF(!string.IsNullOrEmpty(dto.ApplyOrgName), x => x.ApplyOrgName.Contains(dto.ApplyOrgName))        //申请部门
                .WhereIF(dto.ApplyTimeStart.HasValue, x => x.CreationTime >= dto.ApplyTimeStart)                         //申请时间Start
                .WhereIF(dto.ApplyTimeEnd.HasValue, x => x.CreationTime <= dto.ApplyTimeEnd)                             //申请时间End
                .WhereIF(!string.IsNullOrEmpty(dto.AcceptTypeCode), x => x.Order.AcceptTypeCode == dto.AcceptTypeCode)   //受理类型
                .WhereIF(!string.IsNullOrEmpty(dto.Hotspot), x => x.Order.HotspotSpliceName != null && x.Order.HotspotSpliceName.Contains(dto.Hotspot)) //热点
                .WhereIF(dto.Status is ESecondaryHandlingState.Apply, x => x.State == ESecondaryHandlingState.Apply)
                .WhereIF(dto.Status is ESecondaryHandlingState.Handled, x => x.State != ESecondaryHandlingState.Apply)
                .WhereIF(dto.Status is ESecondaryHandlingState.End || dto.Status is ESecondaryHandlingState.Refuse || dto.Status is ESecondaryHandlingState.NotApply, x => x.State == dto.Status)
                .WhereIF(dto.CreationTimeStart.HasValue, x => x.CreationTime >= dto.CreationTimeStart)
                .WhereIF(dto.CreationTimeEnd.HasValue, x => x.CreationTime <= dto.CreationTimeEnd)
                .WhereIF(!string.IsNullOrEmpty(dto.OrderId), x => x.OrderId == dto.OrderId);
            if (_sessionContext.OrgId != null && !_sessionContext.OrgIsCenter)
            {
                quer.Where(x => x.ApplyOrgId.StartsWith(_sessionContext.OrgId));
            }
            return quer.OrderByDescending(x => x.CreationTime);
        }

        /// <summary>
        /// 获取实体
        /// </summary>
        /// <returns></returns>
        public async Task<OrderSecondaryHandling> Entity(string id, CancellationToken cancellationToken)
        {
            return await _orderSecondaryHandlingRepository.Queryable()
                .FirstAsync(x => x.Id == id, cancellationToken);
        }

        /// <summary>
        /// 二次办理统计
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        public ISugarQueryable<SecondaryHandlingVo> SecondaryHandlingReport(QuerySecondaryHandlingRequest dto, CancellationToken cancellationToken)
        {
            var query = _orderSecondaryHandlingRepository.Queryable();

            var isCenter = _sessionContext.OrgIsCenter;
            if (!isCenter)
            {
                query.Where(x => x.ApplyOrgId.StartsWith(_sessionContext.OrgId));
            }

            return query.WhereIF(dto.StartTime.HasValue, x => x.CreationTime >= dto.StartTime)
                        .WhereIF(dto.EndTime.HasValue, x => x.CreationTime <= dto.EndTime)
                        .WhereIF(!string.IsNullOrEmpty(dto.OrgName), x => x.ApplyOrgName.Equals(dto.OrgName))
                        .Where(x => x.State == ESecondaryHandlingState.End)
                        .GroupBy(x => new { x.ApplyOrgId, x.ApplyOrgName })
                        .Select(x => new SecondaryHandlingVo
                        {
                            OrgId = x.ApplyOrgId,
                            OrgName = x.ApplyOrgName,
                            Num = SqlFunc.AggregateCount(x.Id)
                        })
                        .OrderByIF(dto.SortRule is 0, x => x.Num, OrderByType.Asc)
                        .OrderByIF(dto.SortRule is 1, x => x.Num, OrderByType.Desc);
        }

        /// <summary>
        /// 二次办理统计明细
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        public ISugarQueryable<OrderSecondaryHandling> SecondaryHandlingDetailReport(QuerySecondaryHandlingRequest dto, CancellationToken cancellationToken)
        {
            return _orderSecondaryHandlingRepository.Queryable()
                .Includes(x => x.Order)
                .Includes(x => x.Visit)
                .Includes(x => x.VisitDetail)
                .WhereIF(dto.StartTime.HasValue, x => x.CreationTime >= dto.StartTime)
                .WhereIF(dto.EndTime.HasValue, x => x.CreationTime <= dto.EndTime)
                .WhereIF(!string.IsNullOrEmpty(dto.OrgName), x => x.ApplyOrgName.Equals(dto.OrgName))
                .Where(x => x.ApplyOrgId == dto.OrgId)
                .Where(x => x.State == ESecondaryHandlingState.End);
        }


        /// <summary>
        /// 二次办理满意度统计
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        public ISugarQueryable<SecondaryHandlingSatisfactionVo> SecondaryHandlingSatisfactionReport(QuerySecondaryHandlingRequest dto, CancellationToken cancellationToken)
        {
            var query = _orderSecondaryHandlingRepository.Queryable();

            var isCenter = _sessionContext.OrgIsCenter;
            if (!isCenter)
            {
                query.Where(x => x.ApplyOrgId.StartsWith(_sessionContext.OrgId));
            }

            return query
                .Includes(x => x.Order)
                .Includes(x => x.Visit)
                .Includes(x => x.VisitDetail)
                .Includes(x => x.Order, o => o.CallRecord)
                .LeftJoin<SystemOrganize>((x, o) => x.ApplyOrgId == o.Id)
                .WhereIF(dto.StartTime.HasValue, x => x.CreationTime >= dto.StartTime)
                .WhereIF(dto.EndTime.HasValue, x => x.CreationTime <= dto.EndTime)
                .WhereIF(!string.IsNullOrEmpty(dto.OrgName), x => x.ApplyOrgName.Equals(dto.OrgName))
                .WhereIF(!string.IsNullOrEmpty(dto.CDPN), x => x.Order.CallRecord.CDPN.Contains(dto.CDPN))
                .GroupBy((x, o) => new { x.ApplyOrgId, x.ApplyOrgName, o.OrgType })
                .Select((x, o) => new SecondaryHandlingSatisfactionVo()
                {
                    OrgId = x.ApplyOrgId,
                    OrgName = x.ApplyOrgName,
                    OrgType = o.OrgType,
                    TotalSumCount = SqlFunc.AggregateCount(x.Id),
                    VerySatisfiedCount = SqlFunc.IIF(dto.VisitTypeId == 1, SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.VisitDetail.OrgProcessingResults, "Key") == "5", 1, 0)), SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.VisitDetail.OrgHandledAttitude, "Key") == "5", 1, 0))),//非常满意数
                    SatisfiedCount = SqlFunc.IIF(dto.VisitTypeId == 1, SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.VisitDetail.OrgProcessingResults, "Key") == "4", 1, 0)), SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.VisitDetail.OrgHandledAttitude, "Key") == "4", 1, 0))), //满意数
                    RegardedAsSatisfiedCount = SqlFunc.IIF(dto.VisitTypeId == 1, SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.VisitDetail.OrgProcessingResults, "Key") == "-1", 1, 0)), SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.VisitDetail.OrgHandledAttitude, "Key") == "-1", 1, 0))),//视为满意
                    DefaultSatisfiedCount = SqlFunc.IIF(dto.VisitTypeId == 1, SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.VisitDetail.OrgProcessingResults, "Key") == "0", 1, 0)), SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.VisitDetail.OrgHandledAttitude, "Key") == "0", 1, 0))),//默认满意
                    NoSatisfiedCount = SqlFunc.IIF(dto.VisitTypeId == 1, SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.VisitDetail.OrgProcessingResults, "Key") == "2", 1, 0)), SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.VisitDetail.OrgHandledAttitude, "Key") == "2", 1, 0))),//不满意
                    NoEvaluateCount = SqlFunc.IIF(dto.VisitTypeId == 1, SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.VisitDetail.OrgProcessingResults, "Key") == "7", 1, 0)), SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.VisitDetail.OrgHandledAttitude, "Key") == "6", 1, 0))),//未做评价
                    NoPutThroughCount = SqlFunc.IIF(dto.VisitTypeId == 1, SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.VisitDetail.OrgProcessingResults, "Key") == "6", 1, 0)), SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.VisitDetail.OrgHandledAttitude, "Key") == "8", 1, 0))),//未接通
                    NormalCount = SqlFunc.IIF(dto.VisitTypeId == 1, SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.VisitDetail.OrgProcessingResults, "Key") == "3", 1, 0)), SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.VisitDetail.OrgHandledAttitude, "Key") == "3", 1, 0))),//未接通
                    VeryNoSatisfiedCount = SqlFunc.IIF(dto.VisitTypeId == 1, SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.VisitDetail.OrgProcessingResults, "Key") == "1", 1, 0)), SqlFunc.AggregateSum(SqlFunc.IIF(SqlFunc.JsonField(x.VisitDetail.OrgHandledAttitude, "Key") == "1", 1, 0))),//未接通
                });
        }

        /// <summary>
        ///  二次办理满意度统计明细
        /// </summary>
        /// <param name="dto"></param>
        /// <returns></returns>
        public ISugarQueryable<OrderSecondaryHandling> SecondaryHandlingSatisfactionDetailReport(QuerySecondaryHandlingRequest dto, CancellationToken cancellationToken)
        {
            var key = string.Empty;
            if (!string.IsNullOrEmpty(dto.Header))
            {
                switch (dto.Header)
                {
                    case "verySatisfiedCount":
                        key = "5";
                        break;
                    case "satisfiedCount":
                        key = "4";
                        break;
                    case "regardedAsSatisfiedCount":
                        key = "-1";
                        break;
                    case "defaultSatisfiedCount":
                        key = "0";
                        break;
                    case "noSatisfiedCount":
                        key = "2";
                        break;
                    case "noEvaluateCount":
                        key = "7";
                        break;
                    case "noPutThroughCount":
                        key = "6";
                        break;
                }
            }

            return _orderSecondaryHandlingRepository.Queryable()
                .Includes(x => x.Order)
                .Includes(x => x.Visit)
                .Includes(x => x.VisitDetail)
                .Includes(x => x.Order, o => o.CallRecord)
                .WhereIF(dto.StartTime.HasValue, x => x.CreationTime >= dto.StartTime)
                .WhereIF(dto.EndTime.HasValue, x => x.CreationTime <= dto.EndTime)
                .WhereIF(!string.IsNullOrEmpty(dto.OrgName), x => x.ApplyOrgName.Equals(dto.OrgName))
                .WhereIF(!string.IsNullOrEmpty(dto.CDPN), x => x.Order.CallRecord.CDPN.Contains(dto.CDPN))
                .WhereIF(dto.VisitTypeId is 1 && !string.IsNullOrEmpty(key), x => SqlFunc.JsonField(x.VisitDetail.OrgProcessingResults, "Key") == key)
                .WhereIF(dto.VisitTypeId is 2 && !string.IsNullOrEmpty(key), x => SqlFunc.JsonField(x.VisitDetail.OrgHandledAttitude, "Key") == key)
                .WhereIF(!string.IsNullOrEmpty(dto.OrgId), x => x.ApplyOrgId == dto.OrgId)
                .Where(x => x.State == ESecondaryHandlingState.End);
        }

    }
}
