package com.smartor.service.impl;
import com.alibaba.fastjson2.JSON;
import com.alibaba.fastjson2.JSONObject;
import com.fasterxml.jackson.core.JsonProcessingException;
import com.fasterxml.jackson.databind.JsonNode;
import com.fasterxml.jackson.databind.ObjectMapper;
import com.google.gson.Gson;
import com.ruoyi.common.core.domain.entity.SysDept;
import com.ruoyi.common.core.redis.RedisCache;
import com.ruoyi.common.core.service.IConfigService;
import com.ruoyi.common.dx.MessageSend;
import com.ruoyi.common.enums.WxGZHEnum;
import com.ruoyi.common.exception.base.BaseException;
import com.ruoyi.common.utils.*;
import com.ruoyi.common.utils.http.HttpUtils;
import com.ruoyi.common.utils.sms.smsUtils;
import com.ruoyi.common.utils.spring.SpringUtils;
import com.ruoyi.system.domain.SysConfig;
import com.ruoyi.system.mapper.SysConfigMapper;
import com.ruoyi.system.mapper.SysDeptMapper;
import com.ruoyi.system.service.ISysConfigService;
import com.ruoyi.system.service.ISysDeptService;
import com.smartor.common.FtpService;
import com.smartor.common.MtSubmitSmUtil;
import com.smartor.common.ScheduleSubtaskBuilder;
import com.smartor.config.PhoneUtils;
import com.smartor.domain.DTO.MydTrendReqDTO;
import com.smartor.domain.DTO.MzMydScoreRankDTO;
import com.smartor.domain.DTO.QuestionCountKsOrBqDTO;
import com.smartor.domain.DTO.ServiceSubtaskDetailDTO;
import com.smartor.domain.DTO.ServiceSubtaskOptionStatDTO;
import com.smartor.domain.*;
import com.smartor.domain.VO.*;
import com.smartor.domain.entity.ServiceSubtaskEntity;
import com.smartor.mapper.*;
import com.smartor.service.*;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.collections4.MapUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.junit.Test;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.cache.annotation.Cacheable;
import org.springframework.data.redis.core.ListOperations;
import org.springframework.data.redis.core.RedisTemplate;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.web.bind.annotation.RequestBody;
import java.math.BigDecimal;
import java.math.RoundingMode;
import java.net.URLEncoder;
import java.nio.charset.StandardCharsets;
import java.security.MessageDigest;
import java.text.DecimalFormat;
import java.text.SimpleDateFormat;
import java.time.*;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.*;
import java.util.concurrent.Executors;
import java.util.concurrent.ScheduledExecutorService;
import java.util.concurrent.TimeUnit;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import java.util.stream.Collectors;
import static cn.hutool.core.convert.Convert.toHex;
/**
* 单一任务(随访)Service业务层处理
*
* @author ruoyi
* @date 2024-02-02
*/
@Slf4j
@Service
public class ServiceSubtaskServiceImpl implements IServiceSubtaskService {
@Autowired
private ServiceSubtaskMapper serviceSubtaskMapper;
@Autowired
private ServiceSubtaskPreachformMapper serviceSubtaskPreachformMapper;
@Autowired
private ServiceSubtaskDetailMapper serviceSubtaskDetailMapper;
@Autowired
private IServiceTaskService serviceTaskService;
@Autowired
private IvrTaskTemplateTargetoptionMapper serviceTaskScriptTargetoptionMapper;
@Autowired
private IvrTaskVisitResultMapper serviceTaskVisitResultMapper;
@Autowired
private IServiceTaskdeptService serviceTaskdeptService;
@Autowired
private IServiceTaskmedicalService serviceTaskmedicalService;
@Autowired
private IServiceTaskdiagService serviceTaskdiagService;
@Autowired
private IServiceTaskoperService serviceTaskoperService;
@Autowired
private RedisCache redisCache;
@Autowired
private IvrLibaExtemplatescriptMapper ivrLibaExtemplatescriptMapper;
@Autowired
private ISvyTaskTemplateScriptService svyTaskTemplateScriptService;
@Autowired
private IIvrTaskTemplateService ivrTaskTemplateService;
@Autowired
private ISvyTaskTemplateService svyTaskTemplateService;
@Autowired
private IIvrTaskTemplateScriptService iIvrTaskTemplateScriptService;
@Autowired
private IIvrTaskTemplateTargetoptionService iIvrTaskTemplateTargetoptionService;
@Autowired
private IServiceOutPathService iServiceOutPathService;
@Autowired
private IServiceSubtaskDetailTraceService traceService;
@Autowired
private IServiceTaskScheduleService serviceTaskScheduleService;
@Autowired
private IPatArchiveService patArchiveService;
@Autowired
private ISysDeptService sysDeptService;
@Autowired
private ScheduleSubtaskBuilder scheduleSubtaskBuilder;
@Autowired
private FtpService ftpService;
@Autowired
private PatMedInhospMapper patMedInhospMapper;
@Autowired
private PatMedOuthospMapper patMedOuthospMapper;
@Autowired
private PatArchiveMapper patArchiveMapper;
@Autowired
private SvyLibScriptCategoryMapper svyLibScriptCategoryMapper;
@Autowired
private IPatMedInhospService patMedInhospService;
@Value("${pri_key}")
private String pri_key;
@Value("${pub_key}")
private String pub_key;
@Value("${ASRCallBackPath}")
private String ASRCallBackPath;
@Autowired
private ISysConfigService configService;
@Autowired
private MtSubmitSmUtil mtSubmitSmUtil;
@Autowired
private SysConfigMapper sysConfigMapper;
@Autowired
private RedisTemplate redisTemplate;
@Value("${hangup}")
private String hangup;
/**
* 挂断请求最大重试次数(含首次)
*/
private static final int HANGUP_MAX_RETRY = 3;
/**
* 挂断请求重试间隔(毫秒)
*/
private static final long HANGUP_RETRY_INTERVAL_MS = 300L;
/**
* 兜底挂断的最小延时(毫秒):等平台把结束语播完再挂
*/
private static final long HANGUP_FALLBACK_MIN_DELAY_MS = 8000L;
/**
* 兜底挂断定时器。
*
* 雨绮这套的挂断原本依赖"平台播完结束语后再回调一次 PlayEventCallback(playstop=true)",
* 平台不回调电话就一直挂着。这里用一个守护线程池在结束语下发后按字数估算时长做兜底挂断,
* 与平台回调走同一个幂等标记,不会重复挂断。
*/
private ScheduledExecutorService hangupFallbackExecutor;
@Value("${app_key_yq}")
private String app_key_yq;
@Value("${ruoyi.profile}")
private String profile;
@Value("${voicePathPrefix}")
private String voicePathPrefix;
@Value("${localIP}")
private String localIP;
@Value("${req_path}")
private String req_path;
@Value("${xhsmsPath}")
private String xhsmsPath;
@Value("${phoneUpEveryHour}")
private Integer phoneUpEveryHour;
@Value("${phoneEndHour}")
private Integer phoneEndHour;
@Autowired
private IPatMedOuthospService patMedOuthospService;
@Autowired
private SysDept2Mapper sysDept2Mapper;
@Value("${spring.profiles.active}")
private String active;
@Autowired
private ServiceOutPathMapper serviceOutPathMapper;
private static final String KEY_SEP = "\u0001";
/** 二次随访生成锁前缀,防止同一原任务并发生成多条二次随访 */
private static final String AGAIN_LOCK_KEY_PREFIX = "smartor:again:lock:";
private static final long AGAIN_LOCK_SECONDS = 30L;
@Autowired
private PatMedOperationItemMapper patMedOperationItemMapper;
@Autowired
private SysDeptMapper sysDeptMapper;
/**
* 查询单一任务(随访)
*
* @param id 单一任务(随访)主键
* @return 单一任务(随访)
*/
@Override
public ServiceSubtask selectServiceSubtaskById(Long id) {
return serviceSubtaskMapper.selectServiceSubtaskById(id);
}
@Override
public List selectServiceSubtaskByDiagname(ServiceSubtask serviceSubtask) {
return serviceSubtaskMapper.selectServiceSubtaskByDiagname(serviceSubtask);
}
/**
* 查询单一任务(随访)列表
*
* @param serviceSubtaskEntity 单一任务(随访)
* @return 单一任务(随访)
*/
@Override
public List selectServiceSubtaskList(ServiceSubtaskEntity serviceSubtaskEntity) {
return serviceSubtaskMapper.selectServiceSubtaskList(serviceSubtaskEntity);
}
public List selectServiceSubtaskListAgain(ServiceSubtaskEntity serviceSubtaskEntity) {
return serviceSubtaskMapper.selectServiceSubtaskListAgain(serviceSubtaskEntity);
}
@Override
public ServiceTaskVO queryTaskByCondition(ServiceSubtask serviceSubtask) {
//定义患者与单一任务关联表集合
List patTaskRelevances = new ArrayList<>();
ServiceSubtaskEntity serviceSubtaskVO = DtoConversionUtils.sourceToTarget(serviceSubtask, ServiceSubtaskEntity.class);
List list = selectServiceSubtaskList(serviceSubtaskVO);
ServiceTask serviceTask = serviceTaskService.selectServiceTaskByTaskid(serviceSubtask.getTaskid());
if (ObjectUtils.isEmpty(serviceTask)) {
log.error("找不到对应的serviceTask, orgid:{}, taskid: {}", serviceSubtask.getOrgid(), serviceSubtask.getTaskid());
return null;
}
if (CollectionUtils.isEmpty(list) || list.size() == 0) {
ServiceTaskVO serviceTaskVO = DtoConversionUtils.sourceToTarget(serviceTask, ServiceTaskVO.class);
ObjectMapper objectMapper = new ObjectMapper();
try {
List