package com.xinelu.quartz.task;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson2.JSONObject;
import com.xinelu.common.constant.AiobTaskTypeContant;
import com.xinelu.common.constant.Constants;
import com.xinelu.common.core.domain.entity.SysDictData;
import com.xinelu.common.enums.DialStatusEnum;
import com.xinelu.common.enums.NodeExecuteStatusEnum;
import com.xinelu.common.enums.PhoneDialMethodEnum;
import com.xinelu.common.enums.PhoneRedialTimesEnum;
import com.xinelu.common.enums.TaskExcuteTypeEnum;
import com.xinelu.common.utils.StringUtils;
import com.xinelu.common.utils.regex.RegexUtil;
import com.xinelu.common.utils.uuid.UUID;
import com.xinelu.manage.domain.dialtime.DialTime;
import com.xinelu.manage.domain.patientinfo.PatientInfo;
import com.xinelu.manage.domain.patientvisitrecord.PatientVisitRecord;
import com.xinelu.manage.domain.scriptInfo.ScriptInfo;
import com.xinelu.manage.domain.scriptinfotaskinfo.ScriptInfoTaskInfo;
import com.xinelu.manage.domain.signpatientmanageroute.SignPatientManageRoute;
import com.xinelu.manage.domain.signpatientmanageroutenode.SignPatientManageRouteNode;
import com.xinelu.manage.domain.signpatientrecord.SignPatientRecord;
import com.xinelu.manage.dto.aiob.CreateDutyDto;
import com.xinelu.manage.dto.signpatientmanageroutenode.SignPatientManageRouteNodeDto;
import com.xinelu.manage.mapper.labelfieldcontent.LabelFieldContentMapper;
import com.xinelu.manage.mapper.patientinfo.PatientInfoMapper;
import com.xinelu.manage.mapper.patientinfoimportmain.PatientInfoImportMainMapper;
import com.xinelu.manage.mapper.patientvisitrecord.PatientVisitRecordMapper;
import com.xinelu.manage.mapper.scriptInfo.ScriptInfoMapper;
import com.xinelu.manage.mapper.scriptinfotaskinfo.ScriptInfoTaskInfoMapper;
import com.xinelu.manage.mapper.signpatientmanageroute.SignPatientManageRouteMapper;
import com.xinelu.manage.mapper.signpatientmanageroutenode.SignPatientManageRouteNodeMapper;
import com.xinelu.manage.mapper.signpatientrecord.SignPatientRecordMapper;
import com.xinelu.manage.service.signpatientmanageroutenode.ISignPatientManageRouteNodeService;
import com.xinelu.manage.service.yzaiobs.IYZAIOBSService;
import com.xinelu.manage.vo.labelfieldcontent.LabelFieldInfoContentVo;
import com.xinelu.system.service.ISysDictTypeService;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.LocalTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.stream.Collectors;
import javax.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.ObjectUtils;
import org.springframework.stereotype.Component;

/**
 * @description: 曜智智能外呼任务
 * @author: haown
 * @create: 2025-12-26 09:57
 **/
@Slf4j
@Component("YZAIOBSTask")
public class YZAIOBSTask {
	@Resource private SignPatientManageRouteNodeMapper signPatientManageRouteNodeMapper;
	@Resource private ISignPatientManageRouteNodeService signPatientManageRouteNodeService;
	@Resource private SignPatientManageRouteMapper signPatientManageRouteMapper;
	@Resource private SignPatientRecordMapper signPatientRecordMapper;
	@Resource private PatientVisitRecordMapper patientVisitRecordMapper;
	@Resource private ScriptInfoTaskInfoMapper scriptInfoTaskInfoMapper;
	@Resource private IYZAIOBSService iyzaiobsService;
	@Resource private ScriptInfoMapper scriptInfoMapper;
	@Resource private PatientInfoMapper patientInfoMapper;
	@Resource private LabelFieldContentMapper labelFieldContentMapper;
	@Resource private RegexUtil regexUtil;
	@Resource private ISysDictTypeService iSysDictTypeService;
	@Resource private PatientInfoImportMainMapper patientInfoImportMainMapper;

	public void uploadRobotPublishTask() {
		log.info("开始执行曜智智能外呼创建任务定时任务......");
		// 查找需要当天执行的AI打电话任务（问卷或电话外呼类型）
		SignPatientManageRouteNodeDto signPatientManageRouteNodeDto = new SignPatientManageRouteNodeDto();
		//signPatientManageRouteNodeDto.setTaskNodeType(TaskNodeTypeEnum.PHONE_OUTBOUND.getInfo());
		signPatientManageRouteNodeDto.setNodeExecuteStatus(NodeExecuteStatusEnum.UNEXECUTED.getInfo());
		signPatientManageRouteNodeDto.setPhoneDialMethod(PhoneDialMethodEnum.AI.getInfo());
		//只获取 任务执行类型为 批量执行的
		signPatientManageRouteNodeDto.setTaskExcuteType(TaskExcuteTypeEnum.BATCH_TASK.getInfo());
		//查询未拨打的
		signPatientManageRouteNodeDto.setDialStatus(DialStatusEnum.NODIALED.getInfo());

		List<SignPatientManageRouteNode> nodeList = signPatientManageRouteNodeMapper.selectSignPatientManageRouteNodeList(signPatientManageRouteNodeDto);

		List<SignPatientManageRouteNode> executeNodeList = new ArrayList<>();
		nodeList.forEach(node -> {

			LocalDateTime executeTime;
			if (Objects.nonNull(node.getNodePlanTime()) && org.apache.commons.lang3.StringUtils.isNotBlank(node.getNodePlanTime().toString())) {
				executeTime = node.getNodePlanTime();
			} else {
				SignPatientManageRoute signPatientManageRoute = signPatientManageRouteMapper.selectSignPatientManageRouteById(node.getManageRouteId());
				SignPatientRecord signPatientRecord = signPatientRecordMapper.selectByPrimaryKey(signPatientManageRoute.getSignPatientRecordId());
				PatientVisitRecord patientVisitRecord = patientVisitRecordMapper.selectPatientVisitRecordById(signPatientRecord.getPatientVisitRecordId());
				executeTime = signPatientManageRouteNodeService.getExecuteTime(node.getExecuteTime(), node.getRouteNodeName(), node.getRouteNodeDay(), patientVisitRecord);
			}
			//只处理 流水号不为空的
			if (node.getSn() != null &&
				//精确到秒
				node.getScriptInfoId() != null && (executeTime.isBefore(LocalDateTime.now()) || executeTime.isEqual(LocalDateTime.now()))) {
				//精确到天
				// node.getScriptInfoId() != null && (executeTime.toLocalDate().isBefore(LocalDate.now()) || executeTime.toLocalDate().isEqual(LocalDate.now()))) {
				executeNodeList.add(node);
			}
		});
		if (executeNodeList.isEmpty()) return;

		//1、最外层，按照导入流水号分组
		Map<String, List<SignPatientManageRouteNode>> routeNodeGroupListBySn = executeNodeList.stream().collect(Collectors.groupingBy(SignPatientManageRouteNode::getSn));

		// 开始遍历
		routeNodeGroupListBySn.keySet().forEach(sn -> {
			//2、次外层，按照话术ID分组
			Map<Long, List<SignPatientManageRouteNode>> routeNodeGroupListByScriptInfoId =
				routeNodeGroupListBySn.get(sn).stream().collect(Collectors.groupingBy(SignPatientManageRouteNode::getScriptInfoId));
			//开始遍历，生成任务
			routeNodeGroupListByScriptInfoId.keySet().forEach(scriptInfoId -> {
				// 同一分组下的任务节点，配置属性 应该是 是相同的，所以取第0项节点 来使用
				SignPatientManageRouteNode nodeFirstTemp = routeNodeGroupListByScriptInfoId.get(scriptInfoId).get(0);
				//话术
				ScriptInfo scriptInfo = scriptInfoMapper.selectScriptInfoById(scriptInfoId);

				if (ObjectUtils.isNotEmpty(scriptInfo)) {
					// 查询机构拨打时间设置
					LocalTime localStartTime = LocalTime.parse("08:00");
					LocalTime localEndTime = LocalTime.parse("17:00");
					Long hospitalId = patientInfoImportMainMapper.selectHospitalAgencyId(sn);
					if (hospitalId != null) {
						DialTime dialTime = patientInfoImportMainMapper.selectDialTimeById(hospitalId);
						if (ObjectUtils.isNotEmpty(dialTime)) {
							localStartTime = LocalTime.parse(dialTime.getDialStartTime());
							localEndTime = LocalTime.parse(dialTime.getDialEndTime());
							LocalTime dateStartTime;
							LocalTime dateEndTime;
							List<SysDictData> sysDictDataList = iSysDictTypeService.selectDictDataByType(Constants.DIAL_TIME);
							if (CollectionUtils.isEmpty(sysDictDataList) || sysDictDataList.size() != 2) {
								dateStartTime = LocalTime.parse("08:00");
								dateEndTime = LocalTime.parse("17:00");
							} else {
								dateStartTime = LocalTime.parse(sysDictDataList.get(0).getDictValue());
								dateEndTime = LocalTime.parse(sysDictDataList.get(1).getDictValue());
							}
							if (dateStartTime.isAfter(localStartTime)) {
								localStartTime = dateStartTime;
							}
							if (dateEndTime.isBefore(localEndTime)) {
								localEndTime = dateEndTime;
							}
						}
					}


					log.info("创建任务......");
					CreateDutyDto createDutyDto = new CreateDutyDto();

					//临时重复测试用，
					String dutyName = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")) +"S" + scriptInfoId;
					log.info("任务名称：" + dutyName);
					String accountId = UUID.randomUUID().toString().replace("-", "").substring(0, 11);
					createDutyDto.setAccountId(accountId);
					createDutyDto.setDutyName(dutyName);
					createDutyDto.setDutyType(scriptInfo.getRobotPublishId());
					createDutyDto.setDutySceneId(Integer.parseInt(scriptInfo.getRobotPublishId()));
					//createDutyDto.setOutboundPeriods("[\"09:00~11:30\",\"14:00~17:30\"]");
					createDutyDto.setOutboundPeriods("[" + "\"" + localStartTime.format(DateTimeFormatter.ofPattern("HH:mm")) + "~" + localEndTime.format(DateTimeFormatter.ofPattern("HH:mm")) +  "\"" + "]");
					createDutyDto.setStartDate(LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
					createDutyDto.setNoticeSwitch(1);
					createDutyDto.setDeduplicationSwitch(true);
					JSONObject repStrategy = new JSONObject();
					repStrategy.fluentPut("hangState", "").fluentPut("state", "").fluentPut("intention", "");
					createDutyDto.setRepStrategy(repStrategy);
					//3、开始组装本任务下的客户变量
					//遍历最内层任务节点
					JSONArray dataArr = new JSONArray();
					routeNodeGroupListByScriptInfoId.get(scriptInfoId).forEach(node -> {
						SignPatientManageRoute signPatientManageRoute = signPatientManageRouteMapper.selectSignPatientManageRouteById(node.getManageRouteId());
						PatientInfo patientInfo = patientInfoMapper.selectPatientInfoById(signPatientManageRoute.getPatientId());
						//校验手机号
						if (StringUtils.isNotBlank(patientInfo.getPatientPhone())) {
							if (regexUtil.regexPhone(patientInfo.getPatientPhone())) {
								// 查询患者画像信息
								List<LabelFieldInfoContentVo> labelFieldContentList = labelFieldContentMapper.selectByPatientId(patientInfo.getId());
								// 处理变量
								JSONObject jsonObject = new JSONObject();
								jsonObject.fluentPut("手机号", patientInfo.getPatientPhone()).fluentPut("custId", node.getId() + "");
								if (StringUtils.isNotBlank(scriptInfo.getVariables())) {
									List<String> variables = Arrays.asList(scriptInfo.getVariables().split("\\|"));
									variables.forEach(variable -> {
										LabelFieldInfoContentVo labelFieldContent =
											labelFieldContentList.stream().filter(s -> Objects.equals(s.getFieldCode(), variable.replaceAll("_", "").toUpperCase())).findFirst().orElse(null);
										jsonObject.fluentPut(variable, ObjectUtils.isEmpty(labelFieldContent) ? "" : labelFieldContent.getFieldValue());
									});
								}
								dataArr.add(jsonObject);
							}
						}
					});

					createDutyDto.setDataArr(dataArr);
					String taskId = iyzaiobsService.createDuty(createDutyDto);
					if (StringUtils.isNotBlank(taskId)) {
						routeNodeGroupListByScriptInfoId.get(scriptInfoId).forEach(nodeForTask -> {
							ScriptInfoTaskInfo scriptInfoTaskInfo = new ScriptInfoTaskInfo();
							scriptInfoTaskInfo.setScriptInfoId(scriptInfoId);
							scriptInfoTaskInfo.setTaskId(taskId);
							scriptInfoTaskInfo.setRobotId(scriptInfo.getRobotPublishId());
							scriptInfoTaskInfo.setCreateTime(LocalDateTime.now());
							scriptInfoTaskInfo.setSn(sn);
							scriptInfoTaskInfo.setSignPatientManageRouteNodeId(nodeForTask.getId());
							scriptInfoTaskInfo.setSignPatientManageRouteId(nodeForTask.getManageRouteId());
							scriptInfoTaskInfo.setAiobTaskType(AiobTaskTypeContant.BATCHTASK);
							//进入拔打记录表（用于后续重拨处理等判断)----有时间再优化为批量插入
							scriptInfoTaskInfoMapper.insertScriptInfoTaskInfo(scriptInfoTaskInfo);

							//设置拨打状态
							SignPatientManageRouteNode signPatientManageRouteNode_DialStatus = new SignPatientManageRouteNode();
							// signPatientManageRouteNode_DialStatus.setManageRouteId(routeId);
							signPatientManageRouteNode_DialStatus.setId(nodeForTask.getId());
							signPatientManageRouteNode_DialStatus.setDialStatus(DialStatusEnum.DIALED.getInfo());
							signPatientManageRouteNode_DialStatus.setTaskIdExt(taskId);
							signPatientManageRouteNodeMapper.updateDialStatusByNodeId(signPatientManageRouteNode_DialStatus);
						});
					}
				}
			});
		});
		log.info("曜智智能外呼创建任务定时任务执行完成......");
	}

	/**
	 * @return null
	 * @description 创建实时任务
	 * @Author haown
	 * @Date 2024-9-23 10:41
	 */
	public void actualTimeTask() {
		log.info("开始执行曜智智能外呼创建实时任务定时任务......");
		// 查找需要当天执行的AI打电话任务（问卷或电话外呼类型）
		SignPatientManageRouteNodeDto signPatientManageRouteNodeDto = new SignPatientManageRouteNodeDto();
		signPatientManageRouteNodeDto.setNodeExecuteStatus(NodeExecuteStatusEnum.UNEXECUTED.getInfo());
		signPatientManageRouteNodeDto.setPhoneDialMethod(PhoneDialMethodEnum.AI.getInfo());
		//只获取 任务执行类型为 单个执行的
		signPatientManageRouteNodeDto.setTaskExcuteType(TaskExcuteTypeEnum.ACTUAL_TIME_TASK.getInfo());
		//查询未拨打的
		signPatientManageRouteNodeDto.setDialStatus(DialStatusEnum.NODIALED.getInfo());

		List<SignPatientManageRouteNode> nodeList = signPatientManageRouteNodeMapper.selectSignPatientManageRouteNodeList(signPatientManageRouteNodeDto);
		List<SignPatientManageRouteNode> executeNodeList = new ArrayList<>();
		nodeList.forEach(node -> {
			LocalDateTime executeTime;
			//如果有计划执行时间，则直接获取
			if (node.getNodePlanTime() != null) {
				executeTime = node.getNodePlanTime();
			}
			// 否则 ，则根据诊后/院后 第几天 计算
			else {
				SignPatientManageRoute signPatientManageRoute = signPatientManageRouteMapper.selectSignPatientManageRouteById(node.getManageRouteId());
				SignPatientRecord signPatientRecord = signPatientRecordMapper.selectByPrimaryKey(signPatientManageRoute.getSignPatientRecordId());
				PatientVisitRecord patientVisitRecord = patientVisitRecordMapper.selectPatientVisitRecordById(signPatientRecord.getPatientVisitRecordId());
				executeTime = signPatientManageRouteNodeService.getExecuteTime(node.getExecuteTime(), node.getRouteNodeName(), node.getRouteNodeDay(), patientVisitRecord);
			}
			//精确到天
			// if (node.getScriptInfoId() != null && (executeTime.toLocalDate().isBefore(LocalDate.now()) || executeTime.toLocalDate().isEqual(LocalDate.now()))) {
			//精确到秒
			if (node.getScriptInfoId() != null && (executeTime.isBefore(LocalDateTime.now()) || executeTime.isEqual(LocalDateTime.now()))) {
				executeNodeList.add(node);
			}
		});

		// 查询需要重拨的任务
		ScriptInfoTaskInfo scriptInfoTaskInfo = new ScriptInfoTaskInfo();
		scriptInfoTaskInfo.setExecuteStatus(NodeExecuteStatusEnum.UNEXECUTED.getInfo());
		scriptInfoTaskInfo.setAiobTaskType(AiobTaskTypeContant.ACTUALTIMETASK);
		List<ScriptInfoTaskInfo> scriptInfoTaskInfoList = scriptInfoTaskInfoMapper.selectList(scriptInfoTaskInfo);
		scriptInfoTaskInfoList.forEach(taskInfo -> {
			SignPatientManageRouteNode node = signPatientManageRouteNodeMapper.selectSignPatientManageRouteNodeById(taskInfo.getSignPatientManageRouteNodeId());
			if (taskInfo.getExecuteTime().isBefore(LocalDateTime.now()) || taskInfo.getExecuteTime().isEqual(LocalDateTime.now())) {
				executeNodeList.add(node);
			}
		});
		if (CollectionUtils.isNotEmpty(executeNodeList)) {
			// 根据机器人id查询智能外呼系统的任务id
			executeNodeList.forEach(node -> {
				log.info("创建任务......");
				//话术
				ScriptInfo scriptInfo = scriptInfoMapper.selectScriptInfoById(node.getScriptInfoId());
				if (scriptInfo == null) {
					return;
				}
				CreateDutyDto createDutyDto = new CreateDutyDto();

				//临时重复测试用，
				String dutyName = LocalDateTime.now().format(DateTimeFormatter.ofPattern("yyyyMMddHHmmss")) +"NODE" + node.getId();
				log.info("任务名称：" + dutyName);
				String accountId = UUID.randomUUID().toString().replace("-", "").substring(0, 11);
				createDutyDto.setAccountId(accountId);
				createDutyDto.setDutyName(dutyName);
				createDutyDto.setDutyType(scriptInfo.getRobotPublishId());
				createDutyDto.setDutySceneId(Integer.parseInt(scriptInfo.getRobotPublishId()));
				//createDutyDto.setOutboundPeriods("[\"09:00~11:30\",\"14:00~18:30\"]");
				createDutyDto.setOutboundPeriods("[\"08:00~18:30\"]");
				createDutyDto.setStartDate(LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
				createDutyDto.setEndDate(LocalDate.now().format(DateTimeFormatter.ofPattern("yyyy-MM-dd")));
				JSONObject repStrategy = new JSONObject();
				if (StringUtils.isNotBlank(node.getPhoneRedialTimes())) {
					createDutyDto.setDuplication(PhoneRedialTimesEnum.getValueByInfo(node.getPhoneRedialTimes()).getValue());
					createDutyDto.setPeriod(node.getPhoneTimeInterval());
					repStrategy.fluentPut("hangState", "").fluentPut("state", "1,2,4,5,6,7,8").fluentPut("intention", "");
				} else {
					repStrategy.fluentPut("hangState", "").fluentPut("state", "").fluentPut("intention", "");
				}
				createDutyDto.setRepStrategy(repStrategy);
				createDutyDto.setDeduplicationSwitch(true);
				createDutyDto.setNoticeSwitch(1);


				//遍历最内层任务节点
				JSONArray dataArr = new JSONArray();
				SignPatientManageRoute signPatientManageRoute = signPatientManageRouteMapper.selectSignPatientManageRouteById(node.getManageRouteId());
				PatientInfo patientInfo = patientInfoMapper.selectPatientInfoById(signPatientManageRoute.getPatientId());
				//校验手机号
				if (StringUtils.isNotBlank(patientInfo.getPatientPhone())) {
					if (regexUtil.regexPhone(patientInfo.getPatientPhone())) {
						// 查询患者画像信息
						List<LabelFieldInfoContentVo> labelFieldContentList = labelFieldContentMapper.selectByPatientId(patientInfo.getId());
						// 处理变量
						JSONObject jsonObject = new JSONObject();
						jsonObject.fluentPut("custId", node.getId() + "").fluentPut("手机号", patientInfo.getPatientPhone());
						if (StringUtils.isNotBlank(scriptInfo.getVariables())) {
							List<String> variables = Arrays.asList(scriptInfo.getVariables().split("\\|"));
							variables.forEach(variable -> {
								LabelFieldInfoContentVo labelFieldContent =
									labelFieldContentList.stream().filter(s -> Objects.equals(s.getFieldCode(), variable.replaceAll("_", "").toUpperCase())).findFirst().orElse(null);
								jsonObject.fluentPut(variable, ObjectUtils.isEmpty(labelFieldContent) ? "" : labelFieldContent.getFieldValue());
							});
						}
						dataArr.add(jsonObject);
					}
				}

				createDutyDto.setDataArr(dataArr);
				String taskId = iyzaiobsService.createDuty(createDutyDto);
				//设置拨打状态
				if (StringUtils.isNotBlank(taskId)) {
					SignPatientManageRouteNode signPatientManageRouteNode_DialStatus = new SignPatientManageRouteNode();
					signPatientManageRouteNode_DialStatus.setId(node.getId());
					signPatientManageRouteNode_DialStatus.setDialStatus(DialStatusEnum.DIALED.getInfo());
					signPatientManageRouteNode_DialStatus.setTaskIdExt(taskId);
					signPatientManageRouteNodeMapper.updateDialStatusByNodeId(signPatientManageRouteNode_DialStatus);
				}
			});
		}
		log.info("曜智智能外呼创建实时任务定时任务执行完成......");
	}
}
