package com.zt.plat.module.qms.resource.record.service.recordapply;

import cn.hutool.core.collection.CollUtil;
import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.zt.plat.framework.common.pojo.CommonResult;
import com.zt.plat.framework.common.pojo.PageResult;
import com.zt.plat.framework.common.util.object.BeanUtils;
import com.zt.plat.framework.security.core.LoginUser;
import com.zt.plat.framework.security.core.util.SecurityFrameworkUtils;
import com.zt.plat.module.bpm.api.task.BpmProcessInstanceApi;
import com.zt.plat.module.bpm.api.task.dto.BpmProcessInstanceCreateReqDTO;
import com.zt.plat.module.qms.api.task.BMPCallbackInterface;
import com.zt.plat.module.qms.api.task.dto.QmsBpmDTO;
import com.zt.plat.module.qms.business.reportdoc.dal.dataobject.ReportDocumentMainDO;
import com.zt.plat.module.qms.common.data.dal.dataobject.DataCommonType;
import com.zt.plat.module.qms.common.data.dal.dataobject.DataOpinionDO;
import com.zt.plat.module.qms.common.data.service.DataKeyCheckService;
import com.zt.plat.module.qms.common.data.service.DataOpinionService;
import com.zt.plat.module.qms.common.service.BusinessFileService;
import com.zt.plat.module.qms.enums.QmsBpmConstant;
import com.zt.plat.module.qms.enums.QmsCommonConstant;
import com.zt.plat.module.qms.resource.record.common.RecordCommonUtils;
import com.zt.plat.module.qms.resource.record.constant.RecordConstants;
import com.zt.plat.module.qms.resource.record.controller.admin.recordapply.vo.RecordApplyJoinPageVO;
import com.zt.plat.module.qms.resource.record.controller.admin.recordapply.vo.RecordApplyPageReqVO;
import com.zt.plat.module.qms.resource.record.controller.admin.recordapply.vo.RecordApplyRespVO;
import com.zt.plat.module.qms.resource.record.controller.admin.recordapply.vo.RecordApplySaveReqVO;
import com.zt.plat.module.qms.resource.record.controller.admin.recordapplydetail.vo.RecordApplyDetailPageReqVO;
import com.zt.plat.module.qms.resource.record.controller.admin.recordapplydetail.vo.RecordApplyDetailSaveReqVO;
import com.zt.plat.module.qms.resource.record.controller.admin.recordrecord.vo.RecordRecordSaveReqVO;
import com.zt.plat.module.qms.resource.record.dal.dataobject.recordapply.RecordApplyDO;
import com.zt.plat.module.qms.resource.record.dal.dataobject.recordapplydetail.RecordApplyDetailDO;
import com.zt.plat.module.qms.resource.record.dal.dataobject.recordassign.RecordAssignDO;
import com.zt.plat.module.qms.resource.record.dal.dataobject.recordcategory.RecordCategoryDO;
import com.zt.plat.module.qms.resource.record.dal.dataobject.recordpermission.RecordPermissionDO;
import com.zt.plat.module.qms.resource.record.dal.dataobject.recordrecord.RecordRecordDO;
import com.zt.plat.module.qms.resource.record.dal.mapper.RecordApplyMapper;
import com.zt.plat.module.qms.resource.record.service.recordapplydetail.RecordApplyDetailService;
import com.zt.plat.module.qms.resource.record.service.recordassign.RecordAssignService;
import com.zt.plat.module.qms.resource.record.service.recordcategory.RecordCategoryService;
import com.zt.plat.module.qms.resource.record.service.recordpermission.RecordPermissionService;
import com.zt.plat.module.qms.resource.record.service.recordrecord.RecordRecordService;
import com.zt.plat.module.system.api.dept.DeptApi;
import com.zt.plat.module.system.api.dept.dto.DeptRespDTO;
import com.zt.plat.module.system.api.user.AdminUserApi;
import com.zt.plat.module.system.api.user.dto.AdminUserRespDTO;
import jakarta.annotation.Resource;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.ObjectUtils;
import org.springframework.validation.annotation.Validated;

import java.text.SimpleDateFormat;
import java.time.Instant;
import java.time.LocalDateTime;
import java.time.ZoneId;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.IntStream;

import static com.zt.plat.framework.common.exception.util.ServiceExceptionUtil.exception;
import static com.zt.plat.framework.common.exception.util.ServiceExceptionUtil.exception0;
import static com.zt.plat.module.qms.enums.ErrorCodeConstants.*;
import static com.zt.plat.module.qms.enums.QmsBpmConstant.BPM_CALLBACK_BEAN_NAME;

/**
 * 文件记录通用申请 Service 实现类
 *
 * @author 后台管理
 */
@Service("recordApplyService")
@Validated
@Slf4j
public class RecordApplyServiceImpl implements RecordApplyService, BMPCallbackInterface {

    @Resource
    private RecordApplyMapper recordApplyMapper;
    @Resource
    private RecordApplyDetailService recordApplyDetailService;
    @Resource
    private BpmProcessInstanceApi bpmProcessInstanceApi;
    @Resource
    private DataKeyCheckService dataKeyCheckService;
    @Resource
    private DataOpinionService dataOpinionService;

    @Resource
    private RecordRecordService recordRecordService;

    @Resource
    private RecordCategoryService recordCategoryService;

    @Resource
    private RecordPermissionService recordPermissionService;

    @Resource
    private BusinessFileService businessFileService;

    @Resource
    private AdminUserApi adminUserApi;

    @Resource
    private DeptApi deptApi;

    @Resource
    private RecordAssignService recordAssignService;

    @Override
    public RecordApplyRespVO createRecordApply(RecordApplySaveReqVO createReqVO) {
        // 插入
        RecordApplyDO recordApply = BeanUtils.toBean(createReqVO, RecordApplyDO.class);
        recordApplyMapper.insert(recordApply);
        // 返回
        return BeanUtils.toBean(recordApply, RecordApplyRespVO.class);
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public RecordApplyRespVO updateRecordApply(RecordApplySaveReqVO updateReqVO) {
        // 校验存在
//        validateRecordApplyExists(updateReqVO.getId());
        Long applyId = updateReqVO.getId();
        RecordApplyDO recordApplyDO = recordApplyMapper.selectById(applyId);
        if (ObjectUtils.isEmpty(recordApplyDO)) CommonResult.error(RECORD_APPLY_NOT_EXISTS);
        // 查询所有明细
        RecordApplyDO updateObj = BeanUtils.toBean(updateReqVO, RecordApplyDO.class);
        List<RecordApplyDetailDO> detailList = updateObj.getDetailList();
        // 判断更新中的明细是否存在
        //判断  detailList 中的数据 和 数据库中 recordApplyDetail 的数据是否一致,如果有相同的，数据保持不变，有新的，则插入；
        // detailList 中没有的数据，则删除 recordApplyDetail 表中的数据
        List<Long> detailIds = new ArrayList<>();
        List<RecordApplyDetailDO> newDetailList = new ArrayList<>();
        detailList.forEach(item->{
            if (item.getId() != null) detailIds.add(item.getId()); // 有id的
            else {
                item.setApplyId(applyId);
                newDetailList.add( item); // 新数据
            }
        });
        List<RecordApplyDetailDO> deleteDetailAllList = recordApplyDetailService.selectNotInDetailIdList(applyId,detailIds);
        if (!ObjectUtils.isEmpty(deleteDetailAllList)){
            List<Long> deleteDetailIds = deleteDetailAllList.stream().map(RecordApplyDetailDO::getId).toList();
            recordApplyDetailService.deleteRecordApplyDetailListByIds(deleteDetailIds);
        }
        // 更新
        if (!ObjectUtils.isEmpty(newDetailList)) {
            recordApplyDetailService.createRecordApplyDetailBatch(newDetailList);
        }
        String businessType = recordApplyDO.getBusinessType();
        updateReqVO.setBusinessType(businessType);

        recordApplyMapper.updateById(updateObj);

        businessFileService.deleteBusinessFileList(updateReqVO.getDeleteFileIdList());

        return BeanUtils.toBean(updateReqVO, RecordApplyRespVO.class);

    }

    @Override
    public void deleteRecordApply(Long id) {
        // 校验存在
        validateRecordApplyExists(id);
        // 删除
        recordApplyMapper.deleteById(id);
    }

    @Override
    public void deleteRecordApplyListByIds(List<Long> ids) {
        // 校验存在
        validateRecordApplyExists(ids);
        // 删除
        recordApplyMapper.deleteByIds(ids);
    }

    private void validateRecordApplyExists(List<Long> ids) {
        List<RecordApplyDO> list = recordApplyMapper.selectByIds(ids);
        if (CollUtil.isEmpty(list) || list.size() != ids.size()) {
            throw exception(RECORD_APPLY_NOT_EXISTS);
        }
    }

    private void validateRecordApplyExists(Long id) {
        if (recordApplyMapper.selectById(id) == null) {
            throw exception(RECORD_APPLY_NOT_EXISTS);
        }
    }

    @Override
    public RecordApplyDO getRecordApply(Long id) {
        RecordApplyDO recordApplyDO = recordApplyMapper.selectById(id);
        if (ObjectUtils.isEmpty(recordApplyDO)) return recordApplyDO;
        String businessType = recordApplyDO.getBusinessType();
        List<RecordApplyDetailDO> recordApplyDetailDOS;
        if (businessType.equals(RecordConstants.BusinessType.DISTRIBUTION))
            recordApplyDetailDOS = recordApplyDetailService.selectAllList(id);
        else
            recordApplyDetailDOS = recordApplyDetailService.selectDetailAndRecordList(id);
        if (!recordApplyDetailDOS.isEmpty()) recordApplyDO.setDetailList(recordApplyDetailDOS);
        return recordApplyDO;
    }

    @Override
    public PageResult<RecordApplyDO> getRecordApplyPage(RecordApplyPageReqVO pageReqVO) {
        return recordApplyMapper.selectPage(pageReqVO);
    }

    // 创建申请数据
    public RecordApplyDO createApply(RecordApplySaveReqVO param) {
        RecordApplyDO recordApply = BeanUtils.toBean(param, RecordApplyDO.class);
        recordApply.setBusinessStatus(QmsCommonConstant.NOT_START); // 未发起
        recordApply.setApplyStartDate(LocalDateTime.now()); // 申请开始时间
        String businessType = param.getBusinessType();
        //取当前用户
        LoginUser loginUser = SecurityFrameworkUtils.getLoginUser();
        String nickName = SecurityFrameworkUtils.getLoginUserNickname();
        recordApply.setApplyUserId(loginUser.getId());
        recordApply.setApplyUserName(nickName);
        Long visitDeptId = loginUser.getVisitDeptId();
        // 获取当前用户所在的部门
        if (ObjectUtils.isEmpty(visitDeptId))
            throw exception0(RECORD_APPLY_NOT_EXISTS.getCode(), "获取当前部门信息失败");
        recordApply.setApplyDepartmentId(visitDeptId);
        recordApply.setApplyDepartmentName(loginUser.getVisitDeptName());

        //生成标题
        String title = nickName + "的" + businessType + "_" + new SimpleDateFormat("yyyy-MM-dd_HH:mm:ss").format(new Date());
        recordApply.setTitle(title);
        try {
            recordApplyMapper.insert(recordApply);
        } catch (Exception e) {
            throw new RuntimeException(e);
        }
        return recordApply;
    }

    //创建临时数据
    @Override
    @Transactional(rollbackFor = Exception.class)
    public CommonResult<RecordApplyRespVO> createApplyData(RecordApplySaveReqVO param) {
         LoginUser loginUser = SecurityFrameworkUtils.getLoginUser();
        if (ObjectUtils.isEmpty(loginUser)) throw exception0(CURRENT_USER_NOT_EXISTS.getCode(), "用户不存在");

        List<RecordApplyDetailSaveReqVO> detailList = param.getDetailList();
        if (ObjectUtils.isEmpty(detailList))
            throw exception0(RECORD_APPLY_NOT_EXISTS.getCode(), "没有找到文件记录数据");
        // TODO
        RecordApplyDO recordApply = createApply(param);

        return createApplyDetailData(param, recordApply);
    }

    public CommonResult<RecordApplyRespVO> createApplyDetailData(RecordApplySaveReqVO param, RecordApplyDO recordApply) {
        List<RecordApplyDetailDO> detailSaveReqVOList = new ArrayList<>();
        String businessType = param.getBusinessType();
        if (ObjectUtils.isEmpty(businessType))
            throw exception0(RECORD_APPLY_NOT_EXISTS.getCode(), "请选择业务类型");
        switch (businessType) {
            case RecordConstants.BusinessType.REVIEW: // 评审
                detailSaveReqVOList = addReviewDetail(param, recordApply);
                break;
            case RecordConstants.BusinessType.DISTRIBUTION: // 分发
                detailSaveReqVOList = addDistributionDetail(param, recordApply);
                break;
            case RecordConstants.BusinessType.RECORD_UPDATE: // 更改申请
                detailSaveReqVOList = addUpdateDetail(param, recordApply);
                break;
            case RecordConstants.BusinessType.INVALID: // 作废
                detailSaveReqVOList = addInvalidDetail(param, recordApply);
                break;
            case RecordConstants.BusinessType.VIEW_APPLY: // 查看
                detailSaveReqVOList = addViewApplyDetail(param, recordApply);
                break;
            case RecordConstants.BusinessType.RECORD_SUBMIT: // 提交
                Long recordId = param.getDetailList().get(0).getDocumentId(); // 记录Id
                Long applyId = recordApply.getId(); // 申请Id
                detailSaveReqVOList = addRecordSubmitDetail(recordId, applyId);
                break;
        }

        if (ObjectUtils.isEmpty(detailSaveReqVOList))
            throw exception0(RECORD_APPLY_NOT_EXISTS.getCode(), "没有找到文件记录数据");
        boolean recordApplyDetailBatch = recordApplyDetailService.createRecordApplyDetailBatch(detailSaveReqVOList);
        if (!recordApplyDetailBatch)
            throw exception(RECORD_APPLY_NOT_EXISTS, "保存申请明细失败");

        return CommonResult.success(BeanUtils.toBean(recordApply, RecordApplyRespVO.class));
    }

    // 保存评审明细
    public List<RecordApplyDetailDO> addReviewDetail(RecordApplySaveReqVO param, RecordApplyDO recordApplyDO) {
        List<RecordApplyDetailSaveReqVO> detailList = param.getDetailList();
        List<RecordApplyDetailDO> detailSaveReqVOList = new ArrayList<>();
        for (RecordApplyDetailSaveReqVO item : detailList) {
            RecordApplyDetailDO recordApplyDetailDO = new RecordApplyDetailDO();
            recordApplyDetailDO.setApplyId(recordApplyDO.getId());
            recordApplyDetailDO.setDocumentId(item.getDocumentId());
            recordApplyDetailDO.setIsModify(item.getIsModify());
            recordApplyDetailDO.setModifyCause(item.getModifyCause());
            recordApplyDetailDO.setFormData(item.getFormData());
            detailSaveReqVOList.add(recordApplyDetailDO);
        }
        return detailSaveReqVOList;
    }

    // 添加分发明细
    public List<RecordApplyDetailDO> addDistributionDetail(RecordApplySaveReqVO param, RecordApplyDO recordApplyDO) {
        List<RecordApplyDetailSaveReqVO> detailList = param.getDetailList();
        if (ObjectUtils.isEmpty(detailList))
            throw exception0(RECORD_APPLY_DETAIL_NOT_EXISTS.getCode(), "申请明细不存在");

        for (RecordApplyDetailSaveReqVO item : detailList) {
            item.setApplyId(recordApplyDO.getId());
            item.setApplyStartDate(LocalDateTime.now());
        }
        List<RecordApplyDetailDO> bean = BeanUtils.toBean(detailList, RecordApplyDetailDO.class);
        return bean;
    }

    // 添加更改申请明细
    public List<RecordApplyDetailDO> addUpdateDetail(RecordApplySaveReqVO param, RecordApplyDO recordApplyDO) {
        List<RecordApplyDetailSaveReqVO> detailList = param.getDetailList();
        List<RecordApplyDetailDO> detailSaveReqVOList = new ArrayList<>();
        for (RecordApplyDetailSaveReqVO item : detailList) {
            RecordApplyDetailDO recordApplyDetailDO = new RecordApplyDetailDO();
            recordApplyDetailDO.setApplyId(recordApplyDO.getId());
            recordApplyDetailDO.setDocumentId(item.getDocumentId());
            recordApplyDetailDO.setIsModify(item.getIsModify());
            recordApplyDetailDO.setModifyCause(item.getModifyCause());
            recordApplyDetailDO.setFormData(item.getFormData());
            detailSaveReqVOList.add(recordApplyDetailDO);
        }
        return detailSaveReqVOList;
    }

    // 添加作废明细
    public List<RecordApplyDetailDO> addInvalidDetail(RecordApplySaveReqVO param, RecordApplyDO recordApplyDO) {
        List<RecordApplyDetailSaveReqVO> detailList = param.getDetailList();
        List<RecordApplyDetailDO> detailSaveReqVOList = new ArrayList<>();
        for (RecordApplyDetailSaveReqVO item : detailList) {
            RecordApplyDetailDO recordApplyDetailDO = new RecordApplyDetailDO();
            recordApplyDetailDO.setApplyId(recordApplyDO.getId());
            recordApplyDetailDO.setDocumentId(item.getDocumentId());
            recordApplyDetailDO.setIsModify(item.getIsModify());
            recordApplyDetailDO.setModifyCause(item.getModifyCause());
            recordApplyDetailDO.setFormData(item.getFormData());
            detailSaveReqVOList.add(recordApplyDetailDO);
        }
        return detailSaveReqVOList;
    }

    // 添加查看申请
    public List<RecordApplyDetailDO> addViewApplyDetail(RecordApplySaveReqVO param, RecordApplyDO recordApplyDO) {
        List<RecordApplyDetailSaveReqVO> detailList = param.getDetailList();
        List<RecordApplyDetailDO> detailSaveReqVOList = new ArrayList<>();
        for (RecordApplyDetailSaveReqVO item : detailList) {
            RecordApplyDetailDO recordApplyDetailDO = new RecordApplyDetailDO();
            recordApplyDetailDO.setApplyId(recordApplyDO.getId());
            recordApplyDetailDO.setDocumentId(item.getDocumentId());
            Long userId = SecurityFrameworkUtils.getLoginUser().getId();
            recordApplyDetailDO.setTargetId(userId);
            recordApplyDetailDO.setTargetType(RecordConstants.TargetType.USER); // 用户
            recordApplyDetailDO.setIsModify(item.getIsModify());
            recordApplyDetailDO.setModifyCause(item.getModifyCause());
            recordApplyDetailDO.setFormData(item.getFormData());
            detailSaveReqVOList.add(recordApplyDetailDO);
        }
        return detailSaveReqVOList;
    }

    // 添加文件提交明细
    public List<RecordApplyDetailDO> addRecordSubmitDetail(Long recordId, Long applyId) {
        List<RecordApplyDetailDO> detailSaveReqVOList = new ArrayList<>();
        RecordApplyDetailDO recordApplyDetailDO = new RecordApplyDetailDO();
//        Long recordId = param.getDetailList().get(0).getDocumentId();
        recordApplyDetailDO.setApplyId(applyId);
        recordApplyDetailDO.setDocumentId(recordId); // 文件Id
        recordApplyDetailDO.setTargetType(RecordConstants.TargetType.USER);
        LoginUser loginUser = SecurityFrameworkUtils.getLoginUser();
        recordApplyDetailDO.setTargetId(loginUser.getId());
        String loginUserNickname = SecurityFrameworkUtils.getLoginUserNickname();
        recordApplyDetailDO.setTargetName(loginUserNickname);
        detailSaveReqVOList.add(recordApplyDetailDO);
        return detailSaveReqVOList;
    }


    // 判断文件提交是否需要走流程
    public boolean justifyRecordApply(RecordRecordDO recordDO) {
        Integer recordStatus = recordDO.getRecordStatus();
        if (recordStatus != null && recordStatus == 1)
            throw exception(RECORD_APPLY_NOT_EXISTS, "文件已提交，无法提交申请");
        RecordCategoryDO recordCategory = recordCategoryService.getRecordCategory(recordDO.getCategoryId());
        // 获取分类的根分类Id
        String idPath = recordCategory.getIdPath();
        Optional<String> segment = RecordCommonUtils.getSegment(idPath, 1);
        String s = segment.orElse(null);
        if (ObjectUtils.isEmpty(s))
            throw exception(RECORD_APPLY_NOT_EXISTS);
        RecordCategoryDO category = recordCategoryService.getRecordCategory(Long.valueOf(s));
        String customConfig = category.getCustomConfig();
        if (ObjectUtils.isEmpty(customConfig)) { // 空，直接判断是否到生效日期
            // 判断是否到生效日期
            RecordRecordDO effectiveRecordRecordDO = isEffective(recordDO);
            recordRecordService.updateRecordRecordById(effectiveRecordRecordDO);
            return true;
        }
        JSONObject jsonObject = JSONObject.parseObject(customConfig);
        Integer submitFlag = jsonObject.getInteger("submitFlag");
        if (submitFlag == 0) {
            // 不允许提交，直接修改文件记录状态
//            recordDO.setRecordStatus(1); // 已生效
            RecordRecordDO effectiveRecordRecordDO = isEffective(recordDO);
            recordRecordService.updateRecordRecordById(effectiveRecordRecordDO);
            return true;
        } else { // 需要走流程
            // 判断是否到生效日期
//            RecordRecordDO effectiveRecordRecordDO = isEffective(recordDO);
            recordDO.setSubmitFlag("1");
            recordDO.setRecordStatus(0);
            recordRecordService.updateRecordRecordById(recordDO);
        }

        return false;
    }

    // 判断文件记录生效状态
    public RecordRecordDO isEffective(RecordRecordDO recordDO) {
        LocalDateTime effectiveDate = recordDO.getEffectiveDate();
        if (effectiveDate == null) { // 没有生效日期，立即生效
            recordDO.setRecordStatus(1);
        } else {
            recordDO.setRecordStatus(0); // 待生效
            LocalDateTime now = LocalDateTime.now();
            if (now.isAfter(effectiveDate) || now.isEqual(effectiveDate)) {
                recordDO.setRecordStatus(1); // 已生效
            }
        }
        return recordDO;
    }

    public void updateReviewFlag(Long applyId) {
//        Long[] recordIdS = param.getRecordIdS();
        List<RecordApplyDetailDO> recordApplyDetailDOS = recordApplyDetailService.selectAllList(applyId);
        // 修改recordRecord的submitFlag 字段状态为0，评审中
        List<RecordRecordDO> recordRecordDOS = new ArrayList<>();
        for (RecordApplyDetailDO it : recordApplyDetailDOS) {
            RecordRecordDO recordRecordDO = new RecordRecordDO();
            recordRecordDO.setSubmitFlag("0"); // 评审中
            recordRecordDO.setId(it.getDocumentId());
            recordRecordDOS.add(recordRecordDO);
        }
        recordRecordService.updateRecordRecordListByIds(recordRecordDOS);
    }

    //提交申请-发起流程
    @Override
    @Transactional(rollbackFor = Exception.class)
    public CommonResult<RecordApplyRespVO> submitRecordApply(RecordApplySaveReqVO param) {
        LoginUser loginUser = SecurityFrameworkUtils.getLoginUser();
        if (ObjectUtils.isEmpty(loginUser)) throw exception0(RECORD_RECORD_NOT_EXISTS.getCode(), "请重新登录");
        String nickName = SecurityFrameworkUtils.getLoginUserNickname();
        Long applyId = param.getId(); // 申请Id
        String paramBusinessType = param.getBusinessType();
        RecordApplyDO recordApplyDO;
        if (!ObjectUtils.isEmpty(paramBusinessType) && paramBusinessType.equals(RecordConstants.BusinessType.RECORD_SUBMIT)) {
            // 创建申请记录
            CommonResult<RecordApplyRespVO> applyData = createApplyData(param);
            applyId = applyData.getData().getId();

        }
        if (ObjectUtils.isEmpty(applyId)) throw exception0(RECORD_RECORD_NOT_EXISTS.getCode(), "申请记录不存在");
        recordApplyDO = recordApplyMapper.selectById(applyId);

        JSONObject formData = new JSONObject();

        BpmProcessInstanceCreateReqDTO reqDTO = new BpmProcessInstanceCreateReqDTO();

        RecordRecordDO recordRecordDO = new RecordRecordDO();

        reqDTO.setBusinessKey(String.valueOf(applyId));
        String businessType = recordApplyDO.getBusinessType();
        switch (businessType) {
            case RecordConstants.BusinessType.RECORD_SUBMIT:
                // 判断根分类上是否配置自定义配置，允许提交，则需要走流程，否则直接提交
                List<RecordApplyDetailSaveReqVO> detailList = param.getDetailList();
                Long recordId = detailList.get(0).getDocumentId();
                recordRecordDO = recordRecordService.getRecordById(recordId);
                if (ObjectUtils.isEmpty(recordRecordDO))
                    throw exception0(RECORD_RECORD_NOT_EXISTS.getCode(), "文件记录实体不存在");
                boolean b = justifyRecordApply(recordRecordDO);
                if (b) {
                    // 不需要走流程，直接返回成功
                    return CommonResult.success(BeanUtils.toBean(recordRecordDO, RecordApplyRespVO.class));
                }
                reqDTO.setProcessDefinitionKey(RecordConstants.ProcessDefinitionKey.RECORD_SUBMIT_DEFINITION_KEY);
                break;
            case RecordConstants.BusinessType.DISTRIBUTION: // 分发
                reqDTO.setProcessDefinitionKey(RecordConstants.ProcessDefinitionKey.DISTRIBUTION_DEFINITION_KEY);
                // 文件分发需要关联权限表，
                break;
            case RecordConstants.BusinessType.VIEW_APPLY: // 查看申请
                reqDTO.setProcessDefinitionKey(RecordConstants.ProcessDefinitionKey.VIEW_APPLY_DEFINITION_KEY);
                break;
            case RecordConstants.BusinessType.INVALID: // 作废
                reqDTO.setProcessDefinitionKey(RecordConstants.ProcessDefinitionKey.INVALID_DEFINITION_KEY);
                break;
            case RecordConstants.BusinessType.REVIEW: // 评审
                reqDTO.setProcessDefinitionKey(RecordConstants.ProcessDefinitionKey.REVIEW_DEFINITION_KEY);
                // 修改评审状态（null,0,1）
                updateReviewFlag(applyId);
                break;
            case RecordConstants.BusinessType.RECORD_UPDATE: // 文件修改申请
                reqDTO.setProcessDefinitionKey(RecordConstants.ProcessDefinitionKey.RECORD_UPDATE_DEFINITION_KEY);
                break;
            default:
                throw exception(RECORD_APPLY_NOT_EXISTS, "未知的业务类型");
        }

        SimpleDateFormat sdf = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");

        formData.put("mainId", recordApplyDO.getId());
        formData.put("applyUser", nickName);
        formData.put("applyUserId", loginUser.getId());
        formData.put("applyDepartment", loginUser.getVisitDeptName());
        formData.put("applyDepartmentId", loginUser.getVisitDeptId());
        formData.put("applyTime", sdf.format(new Date()));
        formData.put("businessType", businessType);
        formData.put("title", businessType); // 文件名

        Map<String, Object> variables = formData.toJavaObject(Map.class);
        variables.put(BPM_CALLBACK_BEAN_NAME, "recordApplyService");

        reqDTO.setVariables(variables);

        CommonResult<String> result = bpmProcessInstanceApi.createProcessInstance(loginUser.getId(), reqDTO);
        if (!result.isSuccess()) {
            throw exception0(ERROR_CODE_MODULE_COMMON, result.getMsg());
        }

        String wfInsId = result.getData();
        recordApplyDO.setFlowInstanceId(wfInsId);
        // 更新申请实例Id
        recordApplyDO.setBusinessStatus(QmsCommonConstant.IN_PROGRESS); //
        recordApplyMapper.updateById(recordApplyDO);

        // 提交申请-发起流程, 更新 实例Id到文件记录
        if (paramBusinessType.equals(RecordConstants.BusinessType.RECORD_SUBMIT)){
            recordRecordDO.setFlowInstanceId(wfInsId);
            recordRecordDO.setApplyStatus(QmsCommonConstant.IN_PROGRESS);
            recordRecordService.updateRecordRecordById(recordRecordDO);
        }

        return CommonResult.success(BeanUtils.toBean(recordApplyDO, RecordApplyRespVO.class));
    }

    //流程回调
    @Override
    @Transactional(rollbackFor = Exception.class)
    public CommonResult<JSONObject> callback(QmsBpmDTO reqDTO) {
        log.error("文件下发流程回调：{}", JSONObject.toJSONString(reqDTO));
        LoginUser loginUser = SecurityFrameworkUtils.getLoginUser();
        if (ObjectUtils.isEmpty(loginUser))
            throw exception0(CURRENT_USER_DEPT_NOT_EXISTS.getCode(), "当前用户不存在，请重新登录");
        JSONObject variables = reqDTO.getVariables();
        // TODO 目前审批意见在流程回调时保存，后续可以考虑在每个节点完成时保存审批意见，这样可以避免审批意见丢失的情况，同时也能更及时地记录审批意见
        JSONObject taskVariables = variables.getJSONObject("taskVariables");
        String processInsId = variables.getString(QmsBpmConstant.BPM_PROCESS_INS_ID);
        String currentActivityInsId = variables.getString(QmsBpmConstant.BPM_CUR_ACTIVITY_INS_ID);
        String currentActivityId = variables.getString(QmsBpmConstant.BPM_CALLBACK_ACTIVITY_ID);
        String currentActivityName = variables.getString(QmsBpmConstant.BPM_CALLBACK_ACTIVITY_NAME);
        String returnFlag = variables.getString(QmsBpmConstant.BPM_REJECT_TO_FIRST_FLAG);

        String businessType = variables.getString("businessType");
        String mainId = variables.getString("mainId"); // 申请ID

        RecordApplyDO recordApplyDO = recordApplyMapper.selectById(Long.valueOf(mainId)); // 申请记录
        if (recordApplyDO == null) throw exception0(RECORD_APPLY_NOT_EXISTS.getCode(), "申请记录不存在");

        //同一个节点实例只触发一次
        String checkKey = currentActivityInsId;
        if (ObjectUtils.isEmpty(currentActivityInsId))
            checkKey = processInsId + "-create";
        if ("1".equals(returnFlag))
            checkKey += "-reject";
        try {
            dataKeyCheckService.create(checkKey, this.getClass().getName());
        } catch (Exception e) {
            log.error("checkKey 重复：key={}", checkKey);
            return CommonResult.success(new JSONObject());
        }

        //流程状态  1-提交（含退回）  4-取消流程
        String PROCESS_STATUS = variables.getString(QmsBpmConstant.PROCESS_INSTANCE_VARIABLE_STATUS);
        JSONArray fieldExtensions = new JSONArray();
        if(variables.containsKey(QmsBpmConstant.BPM_FIELD_EXTENSIONS)){
            fieldExtensions = variables.getJSONArray(QmsBpmConstant.BPM_FIELD_EXTENSIONS);
        }

        //判断是否最后一个节点
        String lastActivityFlag = "0";
        String firstActivityFlag = "0";
        if(!fieldExtensions.isEmpty()){
            for(int i = 0; i < fieldExtensions.size(); i++){
                JSONObject extension = fieldExtensions.getJSONObject(i);
                String fieldName = extension.getString("fieldName");
                String stringValue = extension.getString("stringValue");
                if(ObjectUtils.isEmpty(stringValue))
                    stringValue = "";
                if(fieldName.equalsIgnoreCase(QmsBpmConstant.BPM_LAST_ACTIVITY_FLAG) && stringValue.equals("1")){
                    lastActivityFlag = "1";
                }
                if(fieldName.equalsIgnoreCase(QmsBpmConstant.BPM_FIRST_ACTIVITY_FLAG) && stringValue.equals("1")){
                    firstActivityFlag = "1";
                }
            }
        }

        List<RecordApplyDetailDO> recordApplyDetailDOS = recordApplyDetailService.selectList(new RecordApplyDetailPageReqVO().setApplyId(Long.valueOf(mainId)));
        //"RETURN_FLAG_Activity_001": true 标识驳回到发起环节
        if(("1").equals(returnFlag)){
            //驳回。流程需要配置退回到发起节点
            log.info("文件下发流程回调：驳回");
            recordApplyDO.setBusinessStatus(QmsCommonConstant.REJECTED);
        }else if("3".equals(PROCESS_STATUS)){
            //作废
            log.info("文件下发流程回调：作废");
            recordApplyDO.setBusinessStatus(QmsCommonConstant.VOID);
            Long documentId = recordApplyDetailDOS.get(0).getDocumentId();
            recordRecordService.updateRecordRecordById(new RecordRecordDO().setId(documentId).setApplyStatus(QmsCommonConstant.VOID));
        }else if("1".equals(PROCESS_STATUS)){
            //通过 保存审批意见
            DataCommonType dataCommonType = new DataCommonType();
            dataCommonType.setBusinessId(Long.valueOf(mainId));
            dataCommonType.setFlowInstanceId(recordApplyDO.getFlowInstanceId());
            dataOpinionService.saveOpinionByWfCallback(dataCommonType, currentActivityId, currentActivityName, taskVariables);
            if("1".equals(lastActivityFlag))
            {
                //通过

                if (ObjectUtils.isEmpty(recordApplyDetailDOS))
                    throw exception0(RECORD_RECORD_NOT_EXISTS.getCode(), "未找到对应的申请明细记录");
                // TODO 业务代码，通过业务类型判断
                List<RecordRecordDO> recordRecordDOS = new ArrayList<>();
                switch (businessType) {
                    case RecordConstants.BusinessType.RECORD_SUBMIT:
                        recordSubmitCallHandle(recordApplyDetailDOS);
                        break;
                    case RecordConstants.BusinessType.REVIEW: // 评审
                        reviewCallHandle(recordApplyDetailDOS);
                        break;
                    case RecordConstants.BusinessType.DISTRIBUTION: // 分发
                        recordPermissionAdd(recordApplyDetailDOS);
                        // 更改申请流程
                        break;
                    case RecordConstants.BusinessType.RECORD_UPDATE: // 修改申请
                        break;
                    case RecordConstants.BusinessType.VIEW_APPLY: // 查看申请
                        recordPermissionAdd(recordApplyDetailDOS);
                        break;
                    case RecordConstants.BusinessType.INVALID: // 作废 -- > 回收权限
                        // 修改文件作废状态
                        for (RecordApplyDetailDO applyDetailDO : recordApplyDetailDOS) {
                            RecordRecordDO recordRecordDO = new RecordRecordDO();
                            recordRecordDO.setId(applyDetailDO.getDocumentId());
                            recordRecordDO.setCancelFlag(1); // 评审通过
                            recordRecordDO.setRecordStatus(0); // 状态 无效
                            recordRecordDOS.add(recordRecordDO);
                        }
                        recordInvalidFlowStatus(recordRecordDOS);
                        break;
                    default:
                        throw exception(RECORD_APPLY_NOT_EXISTS, "未知的业务类型");
                }
                recordApplyDO.setBusinessStatus(QmsCommonConstant.COMPLETED);
            }
        }
        // 审批完成，修改申请通用记录状态为已完成

        recordApplyMapper.updateById(recordApplyDO);

//        String PROCESS_STATUS = variables.getString(QmsBpmConstant.PROCESS_INSTANCE_VARIABLE_STATUS);

//        JSONArray bpmFieldExtensions = variables.getJSONArray("bpmFieldExtensions");
//        String firstActivityFlag = IntStream.range(0, bpmFieldExtensions.size())
//                .mapToObj(bpmFieldExtensions::getJSONObject)
//                .filter(field -> "firstActivityFlag".equals(field.getString("fieldName")))
//                .map(field -> field.getString("stringValue"))
//                .findFirst()
//                .orElse(null);
//
//        log.info("firstActivityFlag:{}", firstActivityFlag);

//        if ("1".equals(firstActivityFlag)) { // 执行到申请人节点，待处理
//            if (PROCESS_STATUS.equals("1")) {
//                return CommonResult.success(ret);
//            } else if ("3".equals(PROCESS_STATUS)) {
//                // 提交流程，发起人拒绝，修改提交状态
//                if (businessType.equals(RecordConstants.BusinessType.RECORD_SUBMIT)){
//                    Long applyId = recordApplyDO.getId();
//                    List<RecordApplyDetailDO> recordApplyDetailDOS = recordApplyDetailService.selectAllList(applyId);
//                    if (ObjectUtils.isEmpty(recordApplyDetailDOS)) throw exception0(RECORD_APPLY_DETAIL_NOT_EXISTS.getCode(),"申请明细不存在");
//                    RecordApplyDetailDO recordApplyDetailDO = recordApplyDetailDOS.get(0);
//                    Long documentId = recordApplyDetailDO.getDocumentId();
//                    RecordRecordDO recordDO = new RecordRecordDO();
//                    recordDO.setId(documentId);
//                    recordDO.setSubmitFlag("0");
//                    recordRecordService.updateRecordRecordById(recordDO);
//                }
//                // 发起人拒绝，申请作废
//                recordApplyDO.setBusinessStatus(QmsCommonConstant.VOID);
//                recordApplyMapper.updateById(recordApplyDO);
//                return CommonResult.success(ret);
//            }
//        }
//
//        // 拒绝，PROCESS_STATUS 状态是3，拒绝。回退上一步流程，修改状态
//        if ("3".equals(PROCESS_STATUS)) {
//            if (businessType.equals(RecordConstants.BusinessType.RECORD_SUBMIT)) {
//                recordApplyDO.setBusinessStatus(QmsCommonConstant.VOID);
//                recordApplyMapper.updateById(recordApplyDO);
//                return CommonResult.success(ret);
//            }
//            String businessStatus = recordApplyDO.getBusinessStatus();
//            if ("running".equals(businessStatus)) {
//                recordApplyDO.setBusinessStatus(QmsCommonConstant.NOT_START);
//            } else if ("not_start".equals(businessStatus)) { // 直接作废
//                recordApplyDO.setBusinessStatus(QmsCommonConstant.VOID);
//            }
//            recordApplyMapper.updateById(recordApplyDO);
//            return CommonResult.success(ret);
//        }

        JSONObject ret = new JSONObject();
        return CommonResult.success(ret);
    }

    public void recordSubmitCallHandle(List<RecordApplyDetailDO> recordApplyDetailDOS) {
        RecordApplyDetailDO recordApplyDetailDO = recordApplyDetailDOS.get(0);
        Long documentId = recordApplyDetailDO.getDocumentId();
        RecordRecordDO entity = recordRecordService.getRecordById(documentId);
        // 判断生效日期
//        LocalDateTime effectiveDate = entity.getEffectiveDate(); // 有效日期
//        if (effectiveDate != null) {
//            // 判断是否到生效日期
//            LocalDateTime now = LocalDateTime.now();
//            if (now.isAfter(effectiveDate) || now.isEqual(effectiveDate)) {
//                entity.setRecordStatus(1); // 已生效
//            }
//        } else {
//            entity.setRecordStatus(1); // 默认已生效
//        }
        RecordRecordDO effectiveRecordRecordDO = isEffective(entity);
        effectiveRecordRecordDO.setApplyStatus(QmsCommonConstant.COMPLETED); // 审批完成
        // 修改状态
        recordApplyFlowStatus(effectiveRecordRecordDO);
    }

    // 评审通过，处理修改修改的文件，走更改申请流程
    public void reviewCallHandle(List<RecordApplyDetailDO> recordApplyDetailDOS) {
        List<RecordApplyDetailSaveReqVO> detailDOList = new ArrayList<>();
        // 1条申请----> 多条明细记录 ----> 多条文件记录
        for (RecordApplyDetailDO applyDetailDO : recordApplyDetailDOS) {
            if (applyDetailDO.getIsModify() == 1) { //是否修改，是：直接创建更改申请
                RecordApplyDetailSaveReqVO detailDO = new RecordApplyDetailSaveReqVO();
                detailDO.setDocumentId(applyDetailDO.getDocumentId());
                detailDOList.add(detailDO);
            }
        }
        // 文件评审通过了，如果需要修改文件，直接申请流程
        if (!ObjectUtils.isEmpty(detailDOList)) {
            RecordApplySaveReqVO recordApplyRespVO = new RecordApplySaveReqVO();
            recordApplyRespVO.setBusinessType(RecordConstants.BusinessType.RECORD_UPDATE);
            recordApplyRespVO.setDetailList(detailDOList);
            createApplyData(recordApplyRespVO);
        }
    }

    // 文件提交-更改状态
    public void recordApplyFlowStatus(RecordRecordDO recordDO) {
        // 修改文件状态为已生效
        recordRecordService.updateRecordRecordById(recordDO);
    }

    // 文件批量跟新状态
    public void recordInvalidFlowStatus(List<RecordRecordDO> recordDO) {
        // 修改文件状态为已生效
        recordRecordService.updateRecordRecordListByIds(recordDO);
        List<Long> list = new ArrayList<>();
        recordDO.forEach(item -> {
            list.add(item.getId());
        });

        // 回收文件权限
        LambdaQueryWrapper<RecordPermissionDO> queryWrapper = new LambdaQueryWrapper<>();
        queryWrapper.eq(RecordPermissionDO::getSourceType, RecordConstants.PermissionSourceType.RECORD);
        queryWrapper.in(RecordPermissionDO::getSourceId, list); // 记录id
        List<RecordPermissionDO> recordPermissionDOS = recordPermissionService.selectList(queryWrapper);
        List<RecordPermissionDO> recordPermissionDOList = new ArrayList<>();
        List<Long> permissionIds = new ArrayList<>();
        for (RecordPermissionDO recordPermissionDO : recordPermissionDOS) {
            recordPermissionDO.setCancelFlag("1");
//            recordPermissionDO.setDeleted(true);
            recordPermissionDOList.add(recordPermissionDO);
        }
        if (!ObjectUtils.isEmpty(recordPermissionDOList))
            recordPermissionService.updateRecordPermissionBatch(recordPermissionDOList);
        // 回收权限
        if (!ObjectUtils.isEmpty(permissionIds)) recordPermissionService.deleteRecordPermissionListByIds(permissionIds);
    }

    /**
     * 将 Object 类型的时间戳转换为 LocalDateTime
     *
     * @param timestamp 时间戳对象（可能是 Long、Date 等类型）
     * @return LocalDateTime 对象
     */
    private static LocalDateTime convertToLocalDateTime(Object timestamp) {
        if (timestamp == null) {
            return null;
        }

        if (timestamp instanceof Date) {
            return ((Date) timestamp).toInstant()
                    .atZone(ZoneId.systemDefault())
                    .toLocalDateTime();
        } else if (timestamp instanceof Long) {
            return Instant.ofEpochMilli((Long) timestamp)
                    .atZone(ZoneId.systemDefault())
                    .toLocalDateTime();
        } else if (timestamp instanceof LocalDateTime) {
            return (LocalDateTime) timestamp;
        }

        return null;
    }

    // 文件分发/申请-添加权限
    public void recordPermissionAdd(List<RecordApplyDetailDO> recordApplyDetailDOS) {
//        String loginUserNickname = SecurityFrameworkUtils.getLoginUserNickname();
        LoginUser loginUser = SecurityFrameworkUtils.getLoginUser();
        String visitDeptName = loginUser.getVisitDeptName();
        for (RecordApplyDetailDO applyDetailDO : recordApplyDetailDOS) {
            // 添加记录
            String targetType = applyDetailDO.getTargetType();
            if (ObjectUtils.isEmpty(targetType))
                throw exception(RECORD_APPLY_NOT_EXISTS, "分发对象类型不能为空");
            // 通过-----> 创建人员权限表记录
            String formData = applyDetailDO.getFormData();
            JSONObject jsonObject = JSONObject.parseObject(formData, JSONObject.class);
            Object expirationDate = jsonObject.getTimestamp("expirationDate");
            LocalDateTime localDateTime = convertToLocalDateTime(expirationDate);
            RecordPermissionDO permissionDO = new RecordPermissionDO();
            permissionDO.setExpirationDate(localDateTime);
            permissionDO.setPermission(RecordConstants.PermissionType.VIEW); // 可查看
            permissionDO.setSourceType(RecordConstants.PermissionSourceType.RECORD); // 记录权限
            permissionDO.setSourceId(applyDetailDO.getDocumentId()); // 文件Id
            permissionDO.setDeptId(loginUser.getVisitDeptId());
            permissionDO.setDeptName(loginUser.getVisitDeptName());
            List<RecordPermissionDO> permissionDOList = new ArrayList<>();
            if (targetType.equals(RecordConstants.TargetType.USER)) {
                permissionDO.setTargetId(String.valueOf(applyDetailDO.getTargetId())); // 用户Id
                permissionDO.setTargetType(RecordConstants.TargetType.USER);
                // TODO
                CommonResult<AdminUserRespDTO> user = adminUserApi.getUser(applyDetailDO.getTargetId());
                AdminUserRespDTO data = user.getData();
                permissionDO.setTargetName(data.getNickname());
            } else if (targetType.equals(RecordConstants.TargetType.DEPT)) { // 部门
                permissionDO.setTargetId(String.valueOf(applyDetailDO.getTargetId())); // 部门Id
                permissionDO.setTargetType(RecordConstants.TargetType.DEPT);
                CommonResult<DeptRespDTO> dept = deptApi.getDept(applyDetailDO.getTargetId());
                DeptRespDTO data = dept.getData();
                permissionDO.setTargetName(data.getName());
            }

            permissionDOList.add(permissionDO);
            boolean b = recordPermissionService.insertRecordPermissionBatch(permissionDOList);
            if (!b) throw exception(RECORD_APPLY_NOT_EXISTS, "保存分发权限失败");
        }
    }

    // 分发
    @Override
    public PageResult<RecordApplyJoinPageVO> recordDistributePage(RecordApplyPageReqVO pageReqVO) {
        Page<RecordApplyPageReqVO> page = new Page<>(pageReqVO.getPageNo(), pageReqVO.getPageSize());
        IPage<RecordApplyJoinPageVO> recordApplyJoinPageVOIPage = recordApplyMapper.recordDistributePage(page, pageReqVO);
        return new PageResult<>(recordApplyJoinPageVOIPage.getRecords(), recordApplyJoinPageVOIPage.getTotal());
    }

    // 更改申请
    @Override
    public PageResult<RecordApplyJoinPageVO> recordUpdatePage(RecordApplyPageReqVO pageReqVO) {
        Page<RecordApplyPageReqVO> page = new Page<>(pageReqVO.getPageNo(), pageReqVO.getPageSize());
        recordApplyMapper.recordUpdatePage(page, pageReqVO);
        return null;
    }

    // 文件作废
    @Override
    public PageResult<RecordApplyJoinPageVO> recordInvalidPage(RecordApplyPageReqVO pageReqVO) {
        Page<RecordApplyPageReqVO> page = new Page<>(pageReqVO.getPageNo(), pageReqVO.getPageSize());
        recordApplyMapper.recordUpdatePage(page, pageReqVO);
        return null;
    }

    //查询提交的流程是否存在没有处理或者通过的的数据
//    public List<RecordApplyDO> selectApplyByStatus(String businessType, java.util.List<Long> documentIds, java.util.List<String> businessStatuses) {
//        return recordApplyMapper.selectApplyByStatus(businessType, documentIds, businessStatuses);
//    }
}