package com.testor.module.hazard.service.impl;

import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.testor.biz.file.controller.SysFileController;
import com.testor.common.util.DateUtil;
import com.testor.module.hazard.dao.THazardConditionConfirmationDao;
import com.testor.module.hazard.model.domain.*;
import com.testor.module.hazard.model.dto.THazardConditionConfirmationDTO;
import com.testor.module.hazard.model.dto.THazardWorkPlanParam;
import com.testor.module.hazard.model.enums.WorkPlanStatusEnum;
import com.testor.module.hazard.service.*;
import com.tongtech.tfw.backend.common.models.exceptions.ServiceException;
import com.tongtech.tfw.backend.core.helper.IdHelper;
import com.tongtech.tfw.backend.core.helper.bean.BeanHelper;
import com.tongtech.tfw.workflow.service.TfwProcessInsService;
import com.tongtech.tfw.workflow.service.dto.ProcessInsStartParams;
import com.tongtech.tfw.workflow.service.dto.ProcessInsStartResult;
import com.xxl.job.core.handler.annotation.XxlJob;
import org.apache.commons.collections4.CollectionUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.stereotype.Service;
import com.tongtech.tfw.backend.common.models.supers.SuperServiceImpl;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.transaction.annotation.Transactional;

import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.*;

/**
 * 安全条件确认Service业务层处理
 * 
 * @author testor-framework
 * @date 2024-12-24 21:53:21
 */
@Service
public class THazardConditionConfirmationServiceImpl extends SuperServiceImpl<THazardConditionConfirmationDao, THazardConditionConfirmation> implements THazardConditionConfirmationService
{
    @Autowired
    private THazardConditionConfirmationDetailsService tHazardConditionConfirmationDetailsService;
    @Autowired
    private THazardWorkPlanService tHazardWorkPlanService;
    @Autowired
    private TfwProcessInsService tfwProcessInsService;
    @Autowired
    private THazardConditionConfirmationRecordService tHazardConditionConfirmationRecordService;

    private static final Logger log = LoggerFactory.getLogger(THazardConditionConfirmationServiceImpl.class);


    @Override
    @Transactional(rollbackFor = Exception.class)
    public THazardConditionConfirmation saveOrUpdateEntity(THazardConditionConfirmationDTO tHazardConditionConfirmationDTO) {
        THazardConditionConfirmation tHazardConditionConfirmation = BeanHelper.beanToBean(tHazardConditionConfirmationDTO, THazardConditionConfirmation.class);
        log.info("保存或更新安全条件确认参数数据：{}", tHazardConditionConfirmation);
        String id = tHazardConditionConfirmationDTO.getId();

        // 查询条件包装器
        /*LambdaQueryWrapper<THazardConditionConfirmation> tHazardConditionConfirmationLambdaQueryWrapper = new LambdaQueryWrapper<THazardConditionConfirmation>()
                .eq(THazardConditionConfirmation::getPlanId, tHazardConditionConfirmationDTO.getPlanId())
                .eq(THazardConditionConfirmation::getWorkTypeId, tHazardConditionConfirmationDTO.getWorkTypeId())
                .orderByDesc(THazardConditionConfirmation::getBatch);
        log.info("tHazardConditionConfirmationLambdaQueryWrapper参数：{}", tHazardConditionConfirmationLambdaQueryWrapper);

        log.info("saveOrUpdateEntity之id值：{}", id);

        // 如果是新增操作
        if (StringUtils.isBlank(id)) {
            // 查询最大批次的记录
            List<THazardConditionConfirmation> hazardConditionConfirmations = this.list(tHazardConditionConfirmationLambdaQueryWrapper);
            log.info("saveOrUpdateEntity之最大批次的记录：{}", hazardConditionConfirmations);
            if (!CollectionUtils.isEmpty(hazardConditionConfirmations)) {
                THazardConditionConfirmation hazardConditionConfirmation = hazardConditionConfirmations.get(0);
                Date createDate = hazardConditionConfirmation.getCreateDate();
                LocalDateTime createDatelocalDateTime = DateUtil.dateToLocalDateTime(createDate);

                log.info("saveOrUpdateEntity之最大批次的记录创建时间：{}", createDatelocalDateTime);
                log.info("saveOrUpdateEntity之当前时间：{}", LocalDateTime.now());
                // 如果当前时间在最大批次的创建时间之后，增加批次
                if (DateUtil.notSameDayAndAfter(LocalDateTime.now(), createDatelocalDateTime)) {
                    tHazardConditionConfirmation.setBatch(hazardConditionConfirmation.getBatch() + 1);
                }else {
                    throw new ServiceException("同一天只能新增一次同作业类型的安全条件确认");
                }
            }
        }else {
            // 如果是更新操作，检查同一批次是否已有其他记录
            THazardConditionConfirmation existingEntity = this.getById(id);
            log.info("saveOrUpdateEntity之更新操作参数数据：{}", existingEntity);
            if (existingEntity != null) {
                Integer batch = existingEntity.getBatch();
                log.info("saveOrUpdateEntity之批次：{}", batch);
                // 检查是否有同一批次但不同ID的记录
                tHazardConditionConfirmationLambdaQueryWrapper.ne(THazardConditionConfirmation::getId, tHazardConditionConfirmationDTO.getId())
                        .eq(THazardConditionConfirmation::getBatch, batch);
                if (this.count(tHazardConditionConfirmationLambdaQueryWrapper) > 0) {
                    throw new RuntimeException("当前计划已存在该作业类型的安全条件确认");
                }
            }
        }*/

        // 查询同一计划、作业类型的最大批次
        Integer maxBatch = this.lambdaQuery()
                .eq(THazardConditionConfirmation::getPlanId, tHazardConditionConfirmationDTO.getPlanId())
                .eq(THazardConditionConfirmation::getWorkTypeId, tHazardConditionConfirmationDTO.getWorkTypeId())
                .select(THazardConditionConfirmation::getBatch, THazardConditionConfirmation::getCreateDate)
                .orderByDesc(THazardConditionConfirmation::getBatch)
                .last("LIMIT 1")
                .oneOpt()
                .map(THazardConditionConfirmation::getBatch)
                .orElse(0);

        // 新增操作
        if (StringUtils.isBlank(id)) {
            if (maxBatch > 0) {
                // 查询最大批次的创建日期
                THazardConditionConfirmation maxRecord = this.lambdaQuery()
                        .eq(THazardConditionConfirmation::getPlanId, tHazardConditionConfirmationDTO.getPlanId())
                        .eq(THazardConditionConfirmation::getWorkTypeId, tHazardConditionConfirmationDTO.getWorkTypeId())
                        .eq(THazardConditionConfirmation::getBatch, maxBatch)
                        .orderByDesc(THazardConditionConfirmation::getCreateDate)
                        .last("LIMIT 1")
                        .one();

                LocalDate maxDate = maxRecord.getCreateDate().toInstant().atZone(ZoneId.systemDefault()).toLocalDate();
                LocalDate today = LocalDate.now();

                if (!today.isEqual(maxDate)) {
                    // 跨天，新批次 = 最大批次 + 1
                    tHazardConditionConfirmation.setBatch(maxBatch + 1);
                } else {
                    throw new ServiceException("同一天只能新增一次同作业类型的安全条件确认");
                }
            } else {
                tHazardConditionConfirmation.setBatch(1);
            }
        } else {
            // 更新操作逻辑
            THazardConditionConfirmation existingEntity = this.getById(id);
            if (existingEntity != null) {
                Integer batch = existingEntity.getBatch();
                // 检查同一批次是否有重复
                long count = this.lambdaQuery()
                        .eq(THazardConditionConfirmation::getPlanId, tHazardConditionConfirmationDTO.getPlanId())
                        .eq(THazardConditionConfirmation::getWorkTypeId, tHazardConditionConfirmationDTO.getWorkTypeId())
                        .eq(THazardConditionConfirmation::getBatch, batch)
                        .ne(THazardConditionConfirmation::getId, id)
                        .count();
                if (count > 0) {
                    throw new ServiceException("当前计划已存在该作业类型的安全条件确认");
                }
            }
        }

        log.info("保存或更新tHazardConditionConfirmation：{}", tHazardConditionConfirmation);
        // 保存或更新
        this.saveOrUpdate(tHazardConditionConfirmation);

        // 删除之前的关联详情数据
        tHazardConditionConfirmationDetailsService.remove(new QueryWrapper<THazardConditionConfirmationDetails>().eq("condition_confirmation_id", tHazardConditionConfirmation.getId()));

        // 保存新的关联详情数据
        List<THazardConditionConfirmationDetails> tHazardConditionConfirmationDetails = tHazardConditionConfirmationDTO.getTHazardConditionConfirmationDetails();
        for (THazardConditionConfirmationDetails detail : tHazardConditionConfirmationDetails) {
            detail.setConditionConfirmationId(tHazardConditionConfirmation.getId());
            detail.setPlanId(tHazardConditionConfirmation.getPlanId());
        }
        tHazardConditionConfirmationDetailsService.saveBatch(tHazardConditionConfirmationDetails);  // 使用批量保存方法提高性能

        return tHazardConditionConfirmation;
    }

    @Override
    public THazardConditionConfirmationDTO getDetailsById(String planId, String workTypeId, String batch) {
        THazardConditionConfirmation tHazardConditionConfirmation = this.getOne(new LambdaQueryWrapper<THazardConditionConfirmation>()
                .eq(THazardConditionConfirmation::getPlanId, planId)
                .eq(THazardConditionConfirmation::getWorkTypeId, workTypeId)
                .eq(THazardConditionConfirmation::getBatch, batch)
        );
        if (tHazardConditionConfirmation == null) {
            return null;
        }
        THazardWorkPlan tHazardWorkPlan = tHazardWorkPlanService.getById(tHazardConditionConfirmation.getPlanId());
        THazardConditionConfirmationDTO tHazardConditionConfirmationDTO = BeanHelper.beanToBean(tHazardConditionConfirmation, THazardConditionConfirmationDTO.class);
        tHazardConditionConfirmationDTO.setTHazardConditionConfirmationDetails(tHazardConditionConfirmationDetailsService.list(new QueryWrapper<THazardConditionConfirmationDetails>().eq("condition_confirmation_id", tHazardConditionConfirmation.getId())));
        //作业单位
        tHazardConditionConfirmationDTO.setWorkUnitName(tHazardWorkPlanService.getOrgNamesByOrgId(tHazardWorkPlan.getWorkUnit()));
        //作业现场负责人
        tHazardConditionConfirmationDTO.setWorkSiteResponsibleName(tHazardWorkPlanService.getUserNamesByUserIds(tHazardWorkPlan.getWorkSiteResponsible()));
        //作业地点
        tHazardConditionConfirmationDTO.setWorkLocation(tHazardWorkPlan.getWorkLocation());
        //监护人
        tHazardConditionConfirmationDTO.setGuardianName(tHazardWorkPlanService.getUserNamesByUserIds(tHazardWorkPlan.getGuardian()));
        //作业级别
        tHazardConditionConfirmationDTO.setWorkLevelName(tHazardWorkPlan.getWorkLevel());
        //安全管理部门人员名称
        tHazardConditionConfirmationDTO.setDepartmentName(tHazardWorkPlanService.getUserNamesByUserIds(tHazardConditionConfirmation.getDepartment()));
        return tHazardConditionConfirmationDTO;
    }

    @XxlJob("hazardousWorkDailyCheck")
    @Override
    public void hazardousWorkDailyCheck(String todayStr){
        LocalDate today = LocalDate.now();
        if (StringUtils.isBlank(todayStr)) {
            todayStr = today.format(DateTimeFormatter.ISO_DATE);
        }
        //查询所有未完成的工作计划,且状态不为关闭或取消或已超时(关闭时判断结束时间在当前时间之前设置的状态)
        /*THazardWorkPlanParam tHazardWorkPlanParam = new THazardWorkPlanParam();
        tHazardWorkPlanParam.setActualStartTime(new Date());*/
        QueryWrapper<THazardWorkPlan> query = new QueryWrapper<>();
        query.le(THazardWorkPlan.ACTUAL_START_TIME, new Date());
        query.isNotNull(THazardWorkPlan.ACTUAL_START_TIME);
        query.ne(THazardWorkPlan.WORK_STATUS, WorkPlanStatusEnum.CLOSED.getValue());
        query.ne(THazardWorkPlan.WORK_STATUS, WorkPlanStatusEnum.CANCELED.getValue());
        query.ne(THazardWorkPlan.WORK_STATUS, WorkPlanStatusEnum.OVERDUE.getValue());
        query.ne(THazardWorkPlan.WORK_STATUS, WorkPlanStatusEnum.DRAFT.getValue());
        List<THazardWorkPlan> tHazardWorkPlans = tHazardWorkPlanService.list(query);
        for (THazardWorkPlan tHazardWorkPlan : tHazardWorkPlans) {
            List<THazardConditionConfirmationRecord> tHazardConditionConfirmations = tHazardConditionConfirmationRecordService.list(new QueryWrapper<THazardConditionConfirmationRecord>()
                    .eq(THazardConditionConfirmationRecord.PLAN_ID, tHazardWorkPlan.getId())
                    .eq(THazardConditionConfirmationRecord.STATUS, "0")
                    .likeRight("create_date", todayStr)
                    .orderByDesc("create_date")
            );
            if(tHazardConditionConfirmations.isEmpty()){
                ProcessInsStartParams processInsStartParams = new ProcessInsStartParams();
                processInsStartParams.setBizKey(tHazardWorkPlan.getId());
                processInsStartParams.setProcessDefinitionKey("hazardousWorkDailyCheck");
                processInsStartParams.setOrgId(tHazardWorkPlan.getOrgId());
                processInsStartParams.setUserId(tHazardWorkPlan.getCreateBy());
                Map<String, Object> varMap = new HashMap<>();
                varMap.put("workSiteResponsible",getSubstringAfterDash(tHazardWorkPlan.getWorkSiteResponsible()));
                processInsStartParams.setVariables(varMap);
                ProcessInsStartResult processInsStartResult = tfwProcessInsService.startProcessInsByKey(processInsStartParams);
                String id = IdHelper.getId32bit();
                THazardConditionConfirmationRecord tHazardConditionConfirmationRecord = new THazardConditionConfirmationRecord();
                tHazardConditionConfirmationRecord.setId(id);
                tHazardConditionConfirmationRecord.setPlanId(tHazardWorkPlan.getId());
                tHazardConditionConfirmationRecord.setProcessId(processInsStartResult.getCode());
                tHazardConditionConfirmationRecordService.save(tHazardConditionConfirmationRecord);
            }
        }
    }

    /**
     * 提取 0-id,1-id ，格式中的id字段 返回如 id1,id2
     * @param input 需要转化的id
     * @return
     */
    public String getSubstringAfterDash(String input) {
        String[] split = input.split(",");
        List<String> ids = new ArrayList<>();
        // 查找"-"的位置
        for (String id : split) {
            int index = id.indexOf("-");
            // 如果找到"-"，则截取"-"后的部分
            if (index != -1) {
                ids.add(id.substring(index + 1));  // 截取"-"后的部分
            }
        }

        // 如果没有"-"，返回原字符串
        return StringUtils.join(ids,",");
    }
}
