package com.bzd.system.service.gxhpz;

import com.bzd.common.config.dao.DaoBase;
import com.bzd.common.config.dao.DaoSupport;
import com.bzd.common.config.dao.PageData;
import com.bzd.common.constant.ScheduleConstants;
import com.bzd.common.utils.DateUtils;
import com.bzd.common.utils.StringUtils;
import com.bzd.common.utils.uuid.IdUtils;
import com.bzd.quartz.domain.SysJob;
import com.bzd.quartz.mapper.SysJobMapper;
import com.bzd.quartz.service.ISysJobService;
import com.bzd.system.service.dtp.SDtpYypzFollowUpSopService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import javax.annotation.Resource;
import java.text.ParseException;
import java.text.SimpleDateFormat;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.time.temporal.ChronoUnit;
import java.util.Calendar;
import java.util.Date;
import java.util.List;
import java.util.Locale;

import static com.bzd.common.utils.ShiroUtils.getSysUser;

@Service
public class FollowTaskService {
    @Autowired
    private DaoBase dao;
    @Resource(name = "daoSupport")
    private DaoSupport daoSupport;
    @Autowired
    private com.bzd.system.service.dtp.SDtpYypzFollowUpSopService SDtpYypzFollowUpSopService;
    @Autowired
    ISysJobService jobService;

    /**
     * 查询列表 
     * @param pd
     * @return 
     * @throws Exception
     */
    public List<PageData> findForList(final PageData pd) throws Exception {
        return (List<PageData>) daoSupport.findForList("followTaskMapper.selectFollowTasks", pd);
    }

    /**
     * 查询单个
     * @param pd
     * @return
     * @throws Exception
     */
    public PageData selectOneById(final PageData pd) throws Exception {
        PageData pdo= (PageData) daoSupport.findForObject("followTaskMapper.selectOneById", pd);
        return pdo;
    }
    private static final SimpleDateFormat SDF_DATE_ONLY = new SimpleDateFormat("yyyy-MM-dd");
    private static final SimpleDateFormat SDF = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
    private static final SimpleDateFormat TIME_FORMAT = new SimpleDateFormat("HH:mm:ss");
    /**
     * 根据下次随访时间添加新任务 随访途中 结束随访 中断随访的情况
     * @param pd
     * @return
     * @throws Exception
     */
    @Transactional(rollbackFor = Exception.class)
    public int addNewFollowTask(final PageData pd) throws Exception {
        PageData pdnew = (PageData) daoSupport.findForObject("followTaskMapper.selectOneById", pd);
        PageData jobPd = (PageData) daoSupport.findForObject("followTaskMapper.getJobByTaskId", pdnew);
        PageData pd3=new PageData();
        pd3.put("id",pdnew.get("nodeId"));
        pd3.put("mdmCode",pdnew.get("mdmCode"));
        PageData Object = (PageData) daoSupport.findForObject("SDtpYypzFollowUpSopMapper.selectSOPNodeDrugById", pd3);
        String createTaskStructures = (String) Object.get("createTaskStructures"); // 生成任务(按)
        String activateNodeRule = (String) Object.get("activateNodeRule"); // 单次节点或周期节点
        String nodeFlag="";
        // 根据不同的生成任务条件和节点规则调用相应的处理方法
        if ("时间条件".equals(createTaskStructures)) {
            if ("单次节点".equals(activateNodeRule)) {
                nodeFlag="ST";
            } else if ("周期节点".equals(activateNodeRule)) {
                nodeFlag="PT";
            }
        } else if ("事件条件".equals(createTaskStructures)) {
            if ("单次节点".equals(activateNodeRule)) {
                nodeFlag="SE";
            } else if ("周期节点".equals(activateNodeRule)) {
                nodeFlag="PE";
            }
        }
        // 执行任务 定时器
        String action="execute";
        // 将 PageData 转换为 SysJob 对象
        SysJob jobp = convertPageDataToSysJob(jobPd);
        PageData nodeConfig = (PageData) daoSupport.findForObject("followTaskMapper.getNodeConfigByNodeId", pdnew);
        // 解析下次随访时间
        String nextFollowTimeStr = (String) pd.get("next_follow_time");
        DateTimeFormatter formatter = DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss");
        LocalDateTime nextFollowTime = LocalDateTime.parse(nextFollowTimeStr, formatter);
        // 设置任务属性
        // 获取 storeId 并安全转换为 Integer
        Integer storeId = Integer.parseInt(pd.get("storeId").toString());
        String mdmCode = (String) pdnew.get("mdmCode");
        String patientId = (String) pdnew.get("patientId");
        long templateIdl = (long) pdnew.get("nodeId");
        String templateId= String.valueOf(templateIdl);
        Integer planId = Integer.parseInt(pd.get("planId").toString());
        Integer taskId = Integer.parseInt(pdnew.get("taskId").toString());
        if (StringUtils.isNotNull(jobp)) {
            SysJob job = new SysJob();
            job.setJobName(jobp.getJobName() + "二次任务"); // 任务名称
            // 获取任务有效期天数
            int taskValidityDays = 0;
            if (StringUtils.isNotNull(nodeConfig)) {
                taskValidityDays = (int) nodeConfig.get("taskValidity"); // 配置的任务有效期天数
            }
            // 计算任务有效期
            LocalDateTime expiryLocalDateTime = nextFollowTime.plus(taskValidityDays, ChronoUnit.DAYS);
            Date expiryDate = Date.from(expiryLocalDateTime.atZone(ZoneId.systemDefault()).toInstant());
            job.setExpiryDate(expiryDate); // 设置任务有效期

            // 生成 Cron 表达式
            String cronExpression = generateCronExpression(nextFollowTime);
            job.setCronExpression(cronExpression); // 设置 Cron 表达式

            // 设置调用目标字符串
            String invokeTarget = String.format("ryTask.triggerTask('%s','%s', '%s', '%s', '%s', '%s', '%s', %d, %d)",
                    nextFollowTime, nodeFlag, action, mdmCode, storeId, patientId, templateId, planId, taskId);
            job.setInvokeTarget(invokeTarget); // 设置调用目标字符串
            job.setTaskId(taskId.toString());
            job.setRemark("回访中断后的二次计划任务");
            job.setCreateBy(getSysUser().getLoginName());
            job.setCreateTime(new Date());
            job.setCurrentExecutionCount(0);
            // 设置其他任务属性
            job.setMisfirePolicy(ScheduleConstants.MISFIRE_FIRE_AND_PROCEED); // Cron 计划策略 执行一次
            job.setJobGroup(jobp.getJobGroup()); //任务组名
            job.setJobName("二次"+jobp.getJobName()); // 任务名称
            job.setConcurrent("1"); // 是否并发执行（0允许 1禁止）
            job.setStatus("0");
            job.setPlanId(planId.toString());
            job.setStoreId(storeId.toString());
            job.setPatientId(patientId);
            job.setTaskId(taskId.toString());
            if(nodeFlag.equals("PE") || nodeFlag.equals("PT")){//如果是周期节点  就要用剩余执行次数+1
                jobp.setRemainingExecutions(jobp.getRemainingExecutions()+1); // 设置剩余执行次数+1
                int j= jobService.updateJob(jobp);
                System.out.println("设置剩余执行次数update job="+j);
            }
            return  jobService.insertJob(job);
        }else {
            return 0;
        }
    }
    /**3 生成表达式*/
    public static String generateCronExpression4(String createdTime, int activateWhichDay, String generationHMS, boolean isActivationJob) {
        // 正确的日期格式
        SimpleDateFormat sdfInput = new SimpleDateFormat("EEE MMM dd HH:mm:ss z yyyy", Locale.US);
        Calendar calendar = Calendar.getInstance();

        try {
            // 解析传入的创建时间
            Date date = sdfInput.parse(createdTime);
            calendar.setTime(date);

            // 加上激活计划的天数
            calendar.add(Calendar.DAY_OF_MONTH, activateWhichDay);

            if (isActivationJob) {
                // 对于激活任务，我们只关心日期部分
                return String.format("%d %d %d %d %d ? %d",
                        0, // 秒
                        0, // 分钟
                        0, // 小时
                        calendar.get(Calendar.DAY_OF_MONTH), // 日
                        calendar.get(Calendar.MONTH) + 1, // 月份（Calendar.MONTH 是从0开始计数的）
                        calendar.get(Calendar.YEAR)); // 年份
            } else {
                // 设置具体执行的小时、分钟和秒
                String[] timeParts = generationHMS.split(":");
                calendar.set(Calendar.HOUR_OF_DAY, Integer.parseInt(timeParts[0]));
                calendar.set(Calendar.MINUTE, Integer.parseInt(timeParts[1]));
                calendar.set(Calendar.SECOND, Integer.parseInt(timeParts[2]));

                // 返回Cron表达式
                return String.format("%d %d %d %d %d ? %d",
                        calendar.get(Calendar.SECOND),
                        calendar.get(Calendar.MINUTE),
                        calendar.get(Calendar.HOUR_OF_DAY),
                        calendar.get(Calendar.DAY_OF_MONTH),
                        calendar.get(Calendar.MONTH) + 1,
                        calendar.get(Calendar.YEAR)); // 添加年份字段
            }
        } catch (ParseException e) {
            // 提供默认值或采取其他措施处理异常
            e.printStackTrace();
            // 这里可以设置一个默认的cron表达式，例如立即执行的任务
            return "0 0 0 * * ? *"; // 默认每天午夜执行的任务，并且包含年份占位符
        }
    }
    /**
     * 根据给定的下次随访时间生成 Cron 表达式
     *
     * @param nextFollowTime 下次随访时间
     * @return Cron 表达式
     */
    private String generateCronExpression(LocalDateTime nextFollowTime) {
        int minute = nextFollowTime.getMinute();
        int hour = nextFollowTime.getHour();
        int dayOfMonth = nextFollowTime.getDayOfMonth();
        int month = nextFollowTime.getMonthValue();
        int year = nextFollowTime.getYear();

        // 构建 Cron 表达式（假设使用的是标准的五字段 Cron 表达式）
        return String.format("%d %d %d %d %d ? %d",
                0, // 秒
                minute,
                hour,
                dayOfMonth,
                month,
                year);
    }
    /**
     * 将 PageData 转换为 SysJob 对象
     *
     * @param pageData PageData 对象
     * @return SysJob 对象
     */
    private SysJob convertPageDataToSysJob(PageData pageData) {
        SysJob sysJob = new SysJob();
        sysJob.setJobName((String) pageData.get("job_name"));
        sysJob.setJobGroup((String) pageData.get("job_group"));
        sysJob.setConcurrent((String) pageData.get("concurrent"));
        sysJob.setPatientId((String) pageData.get("patient_id"));
        sysJob.setMisfirePolicy((String) pageData.get("misfirePolicy"));
        sysJob.setPlanId((String) pageData.get("plan_id"));
        sysJob.setStatus("0");
        // 根据实际情况添加其他字段的转换
        return sysJob;
    }
    /**
     * 添加
     * @param pd
     * @return
     * @throws Exception
     */
    @Transactional(rollbackFor = Exception.class)
    public int save(final PageData pd) throws Exception {
      return  daoSupport.save("followTaskMapper.insertFollowTask", pd);

    }

    /**
     *
     * @param ids
     * @return
     * @throws Exception
     */
    public Integer del(List<String> ids) throws Exception {
        return daoSupport.delete("followTaskMapper.deleteFollowTasksByIds", ids);
    }

    /**
     * 修改配置
     * @param pd
     * @return
     * @throws Exception
     */
    public Integer update(PageData pd) throws Exception {
        String suerForm= (String) pd.get("useForm");
        if(StringUtils.isNotNull(suerForm)){
            PageData pd1=new PageData();
            pd1.put("taskId",pd.get("taskId"));
            pd1.put("planId",pd.get("planId"));
            pd1.put("storeId",pd.get("storeId"));
            pd1.put("patientId",pd.get("patientId"));
            if(suerForm.equals("全量表单")){
                PageData pdObj= (PageData) daoSupport.findForObject("SGxhpzFollowUpRecordsMapper.selectFollowUpRecordsByTaskId", pd1);
                if(StringUtils.isNotNull(pdObj)){
                    pd.put("updatedTime",DateUtils.getTime());
                    pd.put("operator",getSysUser().getLoginName());
                    pd.put("follow_up_id",pdObj.get("id"));
                    int a=  daoSupport.update("SGxhpzFollowUpRecordsMapper.updateSGxhpzFollowUpRecords", pd);
                }else{
                    pd.put("createdTime",DateUtils.getTime());
                    pd.put("operator",getSysUser().getLoginName());
                    int b= daoSupport.save("SGxhpzFollowUpRecordsMapper.insertSGxhpzFollowUpRecords", pd);
                }
            }
        }
        return daoSupport.update("followTaskMapper.updateFollowTask", pd);
    }


    /**
     * 关闭任务
     * @param pd
     * @return
     * @throws Exception
     */
    public Integer closeTask(PageData pd) throws Exception {
        pd.put("taskStatus", "已取消");//0待执行，\r\n1已完成，\r\n2未完成，\r\n3已下发，\r\n4已取消
        pd.put("updatedAt", DateUtils.getTime());//'更新时间'
        pd.put("operator", getSysUser().getLoginName());//'操作人'
        int task = daoSupport.update("followTaskMapper.closeTask", pd);
        PageData pd1 = new PageData();
        pd1.put("taskId", pd.get("taskId"));
        pd1.put("status", 1);//暂停任务
        pd1.put("updateBy", getSysUser().getLoginName());
        pd1.put("remark", "任务关闭");
        //更改job表状态
        int job = daoSupport.update("followTaskMapper.updateJobByTaskId", pd1);
        if (task > 0 || job > 0) {
            return 1;
        } else {
            return -1;
        }
    }


}
