package com.aucma.dms.service.impl;

import com.aucma.common.constant.DmsConstants;
import com.aucma.common.exception.ServiceException;
import com.aucma.common.utils.DateUtils;
import com.aucma.common.utils.SecurityUtils;
import com.aucma.common.utils.uuid.Seq;
import com.aucma.dms.domain.*;
import com.aucma.dms.mapper.*;
import com.aucma.dms.service.IDmsBillsMaintInstanceService;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.dao.DataIntegrityViolationException;
import org.springframework.dao.DuplicateKeyException;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Propagation;
import org.springframework.transaction.annotation.Transactional;

import java.math.BigDecimal;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.List;
import java.util.stream.Collectors;

/**
 * 保养工单Service业务层处理
 *
 * @author Open Platform
 * @date 2024-02-29
 */
@Service
public class DmsBillsMaintInstanceServiceImpl implements IDmsBillsMaintInstanceService {
    private static final Logger log = LoggerFactory.getLogger(DmsBillsMaintInstanceServiceImpl.class);

    @Autowired
    private DmsBillsMaintInstanceMapper dmsBillsMaintInstanceMapper;
    @Autowired
    private DmsPlanMaintMapper dmsPlanMaintMapper;
    @Autowired
    private DmsMaintInstanceActivityMapper dmsMaintInstanceActivityMapper;
    @Autowired
    private DmsBillsMaintDetailMapper dmsBillsMaintDetailMapper;
    @Autowired
    private DmsBillsMaintDetailProjectMapper dmsBillsMaintDetailProjectMapper;

/*    @Autowired
    private RemoteSysCommonService remoteSysCommonService;*/

    /**
     * 查询保养工单
     *
     * @param maintInstanceId 保养工单主键
     * @return 保养工单
     */
    @Override
    public DmsBillsMaintInstance selectDmsBillsMaintInstanceByMaintInstanceId(Long maintInstanceId) {
        return dmsBillsMaintInstanceMapper.selectDmsBillsMaintInstanceByMaintInstanceId(maintInstanceId);
    }

    /**
     * 查询保养工单列表
     *
     * @param dmsBillsMaintInstance 保养工单
     * @return 保养工单
     */
    @Override
    public List<DmsBillsMaintInstance> selectDmsBillsMaintInstanceList(DmsBillsMaintInstance dmsBillsMaintInstance) {
        return dmsBillsMaintInstanceMapper.selectDmsBillsMaintInstanceList(dmsBillsMaintInstance);
    }

    /**
     * 新增保养工单
     *
     * @param planMaintCode 保养计划编号
     * @return 结果
     */
    @Override
    @Transactional
    public int insertDmsBillsMaintInstance(String planMaintCode) {
        String planMaintCodeS = planMaintCode.replaceAll("\"", "");
        DmsPlanMaint dmsPlanMaint = dmsPlanMaintMapper.selectDmsPlanMaintJoinByPlanMaintCode(planMaintCodeS);
        if (dmsPlanMaint == null) {
            log.error("创建保养工单失败: 未找到保养计划 | planMaintCode={}", planMaintCodeS);
            return 0;
        }
        List<DmsPlanMaintDetail> planMaintDetails = dmsPlanMaint.getDmsPlanMaintDetailList();
        if (planMaintDetails == null || planMaintDetails.isEmpty()) {
            log.error("创建保养工单失败: 保养计划无明细数据 | planMaintCode={}, planMaintId={}", planMaintCodeS, dmsPlanMaint.getPlanMaintId());
            return 0;
        }

        DmsBillsMaintInstance dmsBillsMaintInstance = new DmsBillsMaintInstance();

        dmsBillsMaintInstance.setCreateTime(DateUtils.getNowDate());
        dmsBillsMaintInstance.setPlanBeginTime(dmsPlanMaint.getMaintTime());
        dmsBillsMaintInstance.setPlanMaintId(dmsPlanMaint.getPlanMaintId());
        dmsBillsMaintInstance.setBillsMaintCode(Seq.getId(Seq.maintInstanceSeqType, Seq.maintInstanceCode));
        dmsBillsMaintInstance.setMaintStatus(DmsConstants.DMS_BILLS_MAINT_INSTANCE_STATUS_TO_MAINT);
        dmsBillsMaintInstance.setMaintGroup(dmsPlanMaint.getMaintGroup());
        dmsBillsMaintInstance.setMaintSupervisor(dmsPlanMaint.getMaintSupervisor());
        dmsBillsMaintInstance.setMaintLevel(dmsPlanMaint.getMaintLevel());
        dmsBillsMaintInstance.setRemark(dmsPlanMaint.getRemark());

        Date lubeTime = dmsPlanMaint.getMaintTime();
        Long timeLimit = dmsPlanMaint.getTimeLimit();
        dmsBillsMaintInstance.setIsFlag(1l);
        // 已废弃审批流功能
        // dmsBillsMaintInstance.setWfProcessId(103l);
        dmsBillsMaintInstance.setPlanEndTime(new Date(lubeTime.getTime() + timeLimit * 1000l));
        int i = dmsBillsMaintInstanceMapper.insertDmsBillsMaintInstance(dmsBillsMaintInstance);
        DmsMaintInstanceActivity dmsMaintInstanceActivity = new DmsMaintInstanceActivity();
        dmsMaintInstanceActivity.setMaintInstanceId(dmsBillsMaintInstance.getMaintInstanceId());
        dmsMaintInstanceActivity.setMaintGroup(dmsBillsMaintInstance.getMaintGroup());
        dmsMaintInstanceActivity.setMaintLevel(dmsBillsMaintInstance.getMaintLevel());
        dmsMaintInstanceActivity.setMaintSupervisor(dmsBillsMaintInstance.getMaintSupervisor());
        dmsMaintInstanceActivity.setRemark(dmsBillsMaintInstance.getRemark());
        dmsMaintInstanceActivity.setProcessStepOrder(1L);
        int i1 = dmsMaintInstanceActivityMapper.insertDmsMaintInstanceActivity(dmsMaintInstanceActivity);
        batchInsertDmsBillsMaintDetail(dmsPlanMaint, dmsBillsMaintInstance.getMaintInstanceId());
        return i;
    }

    public void batchInsertDmsBillsMaintDetail(DmsPlanMaint dmsPlanMaint, Long maintInstanceId) {
        List<DmsPlanMaintDetail> planMaintDetails = dmsPlanMaint.getDmsPlanMaintDetailList();
        List<DmsBillsMaintDetail> billsMaintDetails = new ArrayList<>();
        planMaintDetails.forEach(planMaintDetail -> {
            DmsBillsMaintDetail dmsBillsMaintDetail = new DmsBillsMaintDetail();
            dmsBillsMaintDetail.setMaintInstanceId(maintInstanceId);
            dmsBillsMaintDetail.setDeviceId(planMaintDetail.getDeviceId());
            dmsBillsMaintDetail.setStationId(planMaintDetail.getMaintStationId());
            dmsBillsMaintDetail.setMaintStandardId(planMaintDetail.getMaintStandardId());
            dmsBillsMaintDetail.setIsFlag(1L);
            dmsBillsMaintDetail.setMaintStatus(1L);
            billsMaintDetails.add(dmsBillsMaintDetail);
        });

        if (!billsMaintDetails.isEmpty()) {
            insertMaintDetailsOneByOne(billsMaintDetails);
        }
        ArrayList<DmsBillsMaintDetailProject> list1 = new ArrayList<>();
        List<DmsBillsMaintDetail> list = dmsBillsMaintDetailMapper.selectDetailList(maintInstanceId);
        for (DmsBillsMaintDetail detail : list) {
            List<DmsBaseMaintProject> projects = dmsBillsMaintDetailMapper.selectPrjectIds(detail.getStationId());
            for (DmsBaseMaintProject project : projects) {
                DmsBillsMaintDetailProject project1 = new DmsBillsMaintDetailProject();
                project1.setBillsMaintDetailId(detail.getBillsMaintDetailId());
//                DmsBaseMaintStation station = dmsBillsMaintDetailMapper.selectMainStation(detail.getStationId());
                project1.setMaintProjectId(project.getMaintProjectId());
                project1.setMaintProjectName(project.getMaintProjectName());
                project1.setMaintProjectDesc(project.getMaintProjectDesc());
                project1.setMaintProjectStatus("2");
                list1.add(project1);
            }

        }
        if (!list1.isEmpty()) {
            dmsBillsMaintInstanceMapper.batchDmsProject(list1);
        }
    }

    @Override
    public int updateDmsBillsMaintInstance(DmsBillsMaintInstance dmsBillsMaintInstance) {
        dmsBillsMaintInstance.setUpdateTime(DateUtils.getNowDate());
        return dmsBillsMaintInstanceMapper.updateDmsBillsMaintInstance(dmsBillsMaintInstance);
    }

    /**
     * 批量删除保养工单
     *
     * @param maintInstanceIds 需要删除的保养工单主键
     * @return 结果
     */
    @Override
    public int deleteDmsBillsMaintInstanceByMaintInstanceIds(Long[] maintInstanceIds) {
        return dmsBillsMaintInstanceMapper.deleteDmsBillsMaintInstanceByMaintInstanceIds(maintInstanceIds);
    }

    /**
     * 删除保养工单信息
     *
     * @param maintInstanceId 保养工单主键
     * @return 结果
     */
    @Override
    public int deleteDmsBillsMaintInstanceByMaintInstanceId(Long maintInstanceId) {
        return dmsBillsMaintInstanceMapper.deleteDmsBillsMaintInstanceByMaintInstanceId(maintInstanceId);
    }

    @Override
    public int insertDmsBillsMaintInstancePDA(DmsBillsMaintInstance dmsBillsMaintInstance) {
        // 已废弃审批流功能 - 以下代码已注释
        // Long aLong = remoteSysCommonService.selectProcessActivityIdByWfProcessId(SecurityConstants.INNER, 103l);
        SimpleDateFormat sdf = new SimpleDateFormat("yyyyMMddHH");
        // dmsBillsMaintInstance.setWfProcessId(103l);
        dmsBillsMaintInstance.setBillsMaintCode(sdf.format(DateUtils.getNowDate()));
        dmsBillsMaintInstance.setMaintStatus(1l);
        dmsBillsMaintInstance.setIsFlag(1l);
        int i = dmsBillsMaintInstanceMapper.insertDmsBillsMaintInstance(dmsBillsMaintInstance);
        //创建保养工单实例节点第一步
        DmsMaintInstanceActivity dmsMaintInstanceActivity = new DmsMaintInstanceActivity();
        dmsMaintInstanceActivity.setMaintInstanceId(dmsBillsMaintInstance.getMaintInstanceId());
        // 已废弃审批流功能
        // dmsMaintInstanceActivity.setProcessActivityId(aLong);
        dmsMaintInstanceActivity.setMaintGroup(dmsBillsMaintInstance.getMaintGroup());
        dmsMaintInstanceActivity.setMaintLevel(dmsBillsMaintInstance.getMaintLevel());
        dmsMaintInstanceActivity.setMaintSupervisor(dmsBillsMaintInstance.getMaintSupervisor());
        dmsMaintInstanceActivity.setRemark(dmsBillsMaintInstance.getRemark());
        dmsMaintInstanceActivity.setProcessStepOrder(1l);
        dmsMaintInstanceActivity.setProcessHandleStatus("1");
        dmsMaintInstanceActivityMapper.insertDmsMaintInstanceActivity(dmsMaintInstanceActivity);
        return i;
    }


    /**
     * 获取最新一条未完成的保养工单
     *
     * @param dmsBillsMaintInstance
     * @return
     */
    @Override
    public DmsBillsMaintInstance getNewestBillsMaintInstance(DmsBillsMaintInstance dmsBillsMaintInstance) {
        dmsBillsMaintInstance.setMaintStatusStr(DmsConstants.DMS_BILLS_MAINT_INSTANCE_STATUS_TO_MAINT
                + "," + DmsConstants.DMS_BILLS_MAINT_INSTANCE_STATUS_MAINTING);
        DmsBillsMaintInstance newestBillsMaintInstance = dmsBillsMaintInstanceMapper
                .selectNewestDmsBillsMaintInstance(dmsBillsMaintInstance);
        if (newestBillsMaintInstance != null) {
            DmsBillsMaintDetail queryBillsMaintDetail = new DmsBillsMaintDetail();
            queryBillsMaintDetail.setMaintInstanceId(newestBillsMaintInstance.getMaintInstanceId());
            List<DmsBillsMaintDetail> dmsBillsMaintDetails = dmsBillsMaintDetailMapper.selectDmsBillsMaintDetailJoinList(queryBillsMaintDetail);
            newestBillsMaintInstance.setDmsBillsMaintDetailList(dmsBillsMaintDetails);
        }
        Long maintLevel = newestBillsMaintInstance.getMaintLevel();
        if (maintLevel == 1) {
            newestBillsMaintInstance.setMaintLevelName("日常保养");
        }
        return newestBillsMaintInstance;
    }


    /**
     * 开始保养
     *
     * @param dmsBillsMaintDetail 保养工单明细
     * @return DmsBillsMaintDetail
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public DmsBillsMaintDetail startMaint(DmsBillsMaintDetail dmsBillsMaintDetail) {
        DmsBillsMaintInstance dmsBillsMaintInstance = dmsBillsMaintInstanceMapper.
                selectDmsBillsMaintInstanceByMaintInstanceId(dmsBillsMaintDetail.getMaintInstanceId());
        Long maintStatus = dmsBillsMaintInstance.getMaintStatus() == null ?
                DmsConstants.DMS_BILLS_MAINT_INSTANCE_STATUS_TO_MAINT : dmsBillsMaintInstance.getMaintStatus();
        if (maintStatus.equals(DmsConstants.DMS_BILLS_MAINT_INSTANCE_STATUS_COMPLETE)) {//保养完成
            throw new ServiceException("已经保养完成");
        }

        Date currentDate = new Date();
        String userName = SecurityUtils.getLoginUser() == null ?
                SecurityUtils.getUsername() : SecurityUtils.getLoginUser().getUser().getNickName() ;
//        String userName = SecurityUtils.getUsername();

        if (maintStatus.equals(DmsConstants.DMS_BILLS_MAINT_INSTANCE_STATUS_TO_MAINT)) {//待保养
            dmsBillsMaintInstance.setMaintStatus(DmsConstants.DMS_BILLS_MAINT_INSTANCE_STATUS_MAINTING);
            dmsBillsMaintInstance.setRealBeginTime(currentDate);
            dmsBillsMaintInstance.setUpdateTime(currentDate);
            dmsBillsMaintInstance.setUpdateBy(SecurityUtils.getUserId());
            dmsBillsMaintInstanceMapper.updateDmsBillsMaintInstance(dmsBillsMaintInstance);

            dmsBillsMaintDetail.setBeginTime(currentDate);
            dmsBillsMaintDetail.setUpdateBy(SecurityUtils.getUserId());
            dmsBillsMaintDetail.setUpdateTime(currentDate);
            dmsBillsMaintDetail.setMaintStatus(DmsConstants.DMS_BILLS_MAINT_INSTANCE_STATUS_MAINTING);

            dmsBillsMaintDetailMapper.updateDmsBillsMaintDetail(dmsBillsMaintDetail);

        }
//        else {//保养中
//            dmsBillsMaintDetail.setUpdateBy(SecurityUtils.getUserId());
//            dmsBillsMaintDetail.setUpdateTime(currentDate);
//            dmsBillsMaintDetailMapper.updateDmsBillsMaintDetail(dmsBillsMaintDetail);
//        }

        DmsBillsMaintDetailProject queryBillsMaintDetailProject = new DmsBillsMaintDetailProject();
        queryBillsMaintDetailProject.setBillsMaintDetailId(dmsBillsMaintDetail.getBillsMaintDetailId());
        List<DmsBillsMaintDetailProject> dmsBillsMaintDetailProjects = dmsBillsMaintDetailProjectMapper.selectDmsBillsMaintDetailProjectList(queryBillsMaintDetailProject);
        dmsBillsMaintDetail.setDmsBillsMaintDetailProjectList(dmsBillsMaintDetailProjects);
        return dmsBillsMaintDetail;
    }


    /**
     * 完成保养
     *
     * @param dmsBillsMaintDetail 保养工单明细
     * @return 结果
     */
    @Override
    @Transactional(rollbackFor = Exception.class)
    public int completeMaint(DmsBillsMaintDetail dmsBillsMaintDetail) {
        List<DmsBillsMaintDetailProject> dmsBillsMaintDetailProjects = dmsBillsMaintDetail.getDmsBillsMaintDetailProjectList();
        Long maintInstanceId = dmsBillsMaintDetail.getMaintInstanceId();
        DmsBillsMaintInstance dmsBillsMaintInstance = dmsBillsMaintInstanceMapper.
                selectDmsBillsMaintInstanceByMaintInstanceId(maintInstanceId);
        Long maintStatus = dmsBillsMaintInstance.getMaintStatus() == null ?
                DmsConstants.DMS_BILLS_MAINT_INSTANCE_STATUS_TO_MAINT : dmsBillsMaintInstance.getMaintStatus();
        if (maintStatus.equals(DmsConstants.DMS_BILLS_MAINT_INSTANCE_STATUS_COMPLETE)) {//保养完成
            throw new ServiceException("已经保养完成");
        }

        if (maintStatus.equals(DmsConstants.DMS_BILLS_MAINT_INSTANCE_STATUS_TO_MAINT)) {//待保养
            throw new ServiceException("请先执行开始保养");
        }

        Date currentDate = new Date();
        String userName = SecurityUtils.getLoginUser() == null ?
                SecurityUtils.getUsername() : SecurityUtils.getLoginUser().getUser().getNickName();

        DmsBillsMaintDetail queryMaintDetail = new DmsBillsMaintDetail();
        queryMaintDetail.setMaintInstanceId(maintInstanceId);
        List<DmsBillsMaintDetail> maintDetails = dmsBillsMaintDetailMapper.selectDmsBillsMaintDetailList(queryMaintDetail);

        /**获取未完成的保养明细，并且需要排除当前提交完成的保养明细*/
        List<DmsBillsMaintDetail> inCompleteMaintDetails = maintDetails.stream().
                filter(maintDetail -> !maintDetail.getBillsMaintDetailId().equals(dmsBillsMaintDetail.getBillsMaintDetailId())
                        && (maintDetail.getMaintStatus() == null || maintDetail.getMaintStatus().equals("")
                        || maintDetail.getMaintStatus().equals(DmsConstants.DMS_BILLS_MAINT_INSTANCE_STATUS_TO_MAINT)
                        || maintDetail.getMaintStatus().equals(DmsConstants.DMS_BILLS_MAINT_INSTANCE_STATUS_MAINTING))).collect(Collectors.toList());

        /**如果已经没有未完成的，则需要将工单修改成已完成，并更新结束时间*/
        if (inCompleteMaintDetails == null || inCompleteMaintDetails.isEmpty()) {
            dmsBillsMaintInstance.setMaintStatus(DmsConstants.DMS_BILLS_MAINT_INSTANCE_STATUS_COMPLETE);
            dmsBillsMaintInstance.setRealEndTime(currentDate);
            dmsBillsMaintInstance.setUpdateTime(currentDate);
            dmsBillsMaintInstance.setUpdateBy(SecurityUtils.getUserId());
            dmsBillsMaintInstanceMapper.updateDmsBillsMaintInstance(dmsBillsMaintInstance);
        }

        //更新保养工单明细项目信息
        for (DmsBillsMaintDetailProject dmsBillsMaintDetailProject : dmsBillsMaintDetailProjects) {
            dmsBillsMaintDetailProject.setMaintProjectStatus(DmsConstants.DMS_MAINT_PROJECT_STATUS_COMPLETE);
            dmsBillsMaintDetailProject.setCreateTime(currentDate);
            dmsBillsMaintDetail.setCreateBy(SecurityUtils.getUserId());
            dmsBillsMaintDetailProjectMapper.updateDmsBillsMaintDetailProject(dmsBillsMaintDetailProject);
        }

        dmsBillsMaintDetail.setEndTime(currentDate);
        dmsBillsMaintDetail.setUpdateBy(SecurityUtils.getUserId());
        dmsBillsMaintDetail.setUpdateTime(currentDate);
        dmsBillsMaintDetail.setMaintStatus(DmsConstants.DMS_BILLS_MAINT_INSTANCE_STATUS_COMPLETE);

        dmsBillsMaintDetailMapper.updateDmsBillsMaintDetail(dmsBillsMaintDetail);


        return 1;
    }

    /**
     * 获取保养工单设备列表（网页版保养执行）
     */
    @Override
    public List<DmsBillsMaintDetail> getDeviceList(Long maintInstanceId) {
        DmsBillsMaintDetail query = new DmsBillsMaintDetail();
        query.setMaintInstanceId(maintInstanceId);
        return dmsBillsMaintDetailMapper.selectDmsBillsMaintDetailJoinList(query);
    }

    /**
     * 更新设备保养状态（简化版，只更新合格/不合格）
     */
    @Override
    @Transactional
    public int updateDeviceStatus(DmsBillsMaintDetail detail) {
        Date currentDate = new Date();

        // 获取保养工单信息
        DmsBillsMaintInstance instance = dmsBillsMaintInstanceMapper
                .selectDmsBillsMaintInstanceByMaintInstanceId(detail.getMaintInstanceId());

        Long maintStatus = instance.getMaintStatus() == null ?
                DmsConstants.DMS_BILLS_MAINT_INSTANCE_STATUS_TO_MAINT : instance.getMaintStatus();

        // 如果工单状态是"待保养"，更新为"保养中"
        if (maintStatus.equals(DmsConstants.DMS_BILLS_MAINT_INSTANCE_STATUS_TO_MAINT)) {
            instance.setMaintStatus(DmsConstants.DMS_BILLS_MAINT_INSTANCE_STATUS_MAINTING);
            instance.setRealBeginTime(currentDate);
            instance.setUpdateTime(currentDate);
            instance.setUpdateBy(SecurityUtils.getUserId());
            dmsBillsMaintInstanceMapper.updateDmsBillsMaintInstance(instance);
        }

        // 更新设备明细状态
        detail.setUpdateTime(currentDate);
        detail.setUpdateBy(SecurityUtils.getUserId());
        detail.setEndTime(currentDate);
        detail.setMaintStatus(DmsConstants.DMS_BILLS_MAINT_INSTANCE_STATUS_COMPLETE);
        int result = dmsBillsMaintDetailMapper.updateDmsBillsMaintDetail(detail);

        // 检查是否所有设备都已保养完成
        DmsBillsMaintDetail query = new DmsBillsMaintDetail();
        query.setMaintInstanceId(detail.getMaintInstanceId());
        List<DmsBillsMaintDetail> details = dmsBillsMaintDetailMapper.selectDmsBillsMaintDetailList(query);

        int completedCount = 0;
        for (DmsBillsMaintDetail d : details) {
            if (d.getMaintStatus() != null && d.getMaintStatus().equals(DmsConstants.DMS_BILLS_MAINT_INSTANCE_STATUS_COMPLETE)) {
                completedCount++;
            }
        }

        // 如果所有设备都完成，更新工单状态为"已完成"
        if (completedCount == details.size()) {
            instance.setMaintStatus(DmsConstants.DMS_BILLS_MAINT_INSTANCE_STATUS_COMPLETE);
            instance.setRealEndTime(currentDate);
            instance.setUpdateTime(currentDate);
            instance.setUpdateBy(SecurityUtils.getUserId());
            dmsBillsMaintInstanceMapper.updateDmsBillsMaintInstance(instance);
        }

        return result;
    }

    /**
     * 定时任务专用：创建已完成状态的保养工单（含明细），所有设备默认保养完成
     * 不依赖SecurityUtils，适合在定时任务上下文中调用
     */
    @Override
    @Transactional(propagation = Propagation.REQUIRES_NEW, rollbackFor = Exception.class)
    public int insertCompletedMaintInstance(String planMaintCode) {
        String planMaintCodeS = planMaintCode.replaceAll("\"", "");
        DmsPlanMaint dmsPlanMaint = dmsPlanMaintMapper.selectDmsPlanMaintJoinByPlanMaintCode(planMaintCodeS);
        if (dmsPlanMaint == null) {
            log.error("定时任务创建已完成保养工单失败: 未找到保养计划 | planMaintCode={}", planMaintCodeS);
            return 0;
        }
        List<DmsPlanMaintDetail> planMaintDetails = dmsPlanMaint.getDmsPlanMaintDetailList();
        if (planMaintDetails == null || planMaintDetails.isEmpty()) {
            log.error("定时任务创建已完成保养工单失败: 保养计划无明细数据 | planMaintCode={}, planMaintId={}, maintLevel={}, maintGroup={}",
                    planMaintCodeS, dmsPlanMaint.getPlanMaintId(), dmsPlanMaint.getMaintLevel(), dmsPlanMaint.getMaintGroup());
            return 0;
        }
        log.info("开始创建已完成保养工单 | planMaintCode={}, planMaintId={}, 明细数量={}",
                planMaintCodeS, dmsPlanMaint.getPlanMaintId(), planMaintDetails.size());

        Long planMaintId = dmsPlanMaint.getPlanMaintId();
        if (planMaintId != null) {
            // 1) 先锁计划行，串行化同一计划的并发生成请求
            Long lockedId = dmsPlanMaintMapper.lockPlanById(planMaintId);
            if (lockedId == null) {
                log.warn("保养计划不存在，跳过工单生成 | planMaintId={}, planMaintCode={}", planMaintId, planMaintCodeS);
                return 0;
            }
            // 2) 再做当天查重（应用层幂等）
            int existCount = dmsBillsMaintInstanceMapper.countByPlanIdAndToday(planMaintId);
            if (existCount > 0) {
                log.debug("保养计划今天已生成工单，跳过 | planMaintId={}, planMaintCode={}", planMaintId, planMaintCodeS);
                return 0;
            }
        }

        // 3) 统一使用 DB 时间，减少应用机/DB 机时钟差异
        Date now = dmsBillsMaintInstanceMapper.selectDbNow();
        if (now == null) {
            now = new Date();
        }
        DmsBillsMaintInstance instance = new DmsBillsMaintInstance();

        instance.setCreateTime(now);
        instance.setPlanBeginTime(now);
        instance.setPlanEndTime(now);
        instance.setRealBeginTime(now);
        instance.setRealEndTime(now);
        instance.setPlanMaintId(dmsPlanMaint.getPlanMaintId());
        instance.setBillsMaintCode(Seq.getId(Seq.maintInstanceSeqType, Seq.maintInstanceCode));
        instance.setMaintStatus(DmsConstants.DMS_BILLS_MAINT_INSTANCE_STATUS_COMPLETE); // 已完成
        instance.setMaintCompRate(BigDecimal.valueOf(100)); // 完成率100%
        instance.setMaintGroup(dmsPlanMaint.getMaintGroup());
        instance.setMaintSupervisor(dmsPlanMaint.getMaintSupervisor());
        instance.setMaintLevel(dmsPlanMaint.getMaintLevel());
        instance.setRemark(dmsPlanMaint.getRemark());
        instance.setIsFlag(1L);
        // 创建人优先使用计划的创建人，若无则使用-1L表示系统自动创建
        instance.setCreateBy(dmsPlanMaint.getCreateBy() != null ? dmsPlanMaint.getCreateBy() : -1L);

        int i;
        try {
            i = dmsBillsMaintInstanceMapper.insertDmsBillsMaintInstance(instance);
        } catch (DuplicateKeyException e) {
            log.debug("保养工单触发唯一约束(重复生成)，跳过 | planMaintId={}, billsMaintCode={}",
                    instance.getPlanMaintId(), instance.getBillsMaintCode());
            return 0;
        } catch (DataIntegrityViolationException e) {
            if (isOracleUniqueViolation(e)) {
                log.debug("保养工单触发 ORA-00001(重复生成)，跳过 | planMaintId={}, billsMaintCode={}",
                        instance.getPlanMaintId(), instance.getBillsMaintCode());
                return 0;
            }
            throw e;
        }

        // 创建工单实例节点（第一步）
        DmsMaintInstanceActivity activity = new DmsMaintInstanceActivity();
        activity.setMaintInstanceId(instance.getMaintInstanceId());
        activity.setMaintGroup(instance.getMaintGroup());
        activity.setMaintLevel(instance.getMaintLevel());
        activity.setMaintSupervisor(instance.getMaintSupervisor());
        activity.setRemark(instance.getRemark());
        activity.setProcessStepOrder(1L);
        activity.setProcessHandleStatus("3"); // 已完成
        dmsMaintInstanceActivityMapper.insertDmsMaintInstanceActivity(activity);

        // 创建保养工单明细（所有设备均为已完成状态）
        List<DmsBillsMaintDetail> billsMaintDetails = new ArrayList<>();
        for (DmsPlanMaintDetail planDetail : planMaintDetails) {
            DmsBillsMaintDetail detail = new DmsBillsMaintDetail();
            detail.setMaintInstanceId(instance.getMaintInstanceId());
            detail.setDeviceId(planDetail.getDeviceId());
            detail.setStationId(planDetail.getMaintStationId());
            detail.setMaintStandardId(planDetail.getMaintStandardId());
            detail.setIsFlag(1L);
            detail.setMaintStatus(DmsConstants.DMS_BILLS_MAINT_INSTANCE_STATUS_COMPLETE); // 已完成
            detail.setCreateTime(now);
            billsMaintDetails.add(detail);
        }
        if (!billsMaintDetails.isEmpty()) {
            insertMaintDetailsOneByOne(billsMaintDetails);
        }

        // 创建保养工单明细项目（所有项目均为已完成状态）
        List<DmsBillsMaintDetail> insertedDetails = dmsBillsMaintDetailMapper.selectDetailList(instance.getMaintInstanceId());
        ArrayList<DmsBillsMaintDetailProject> projectList = new ArrayList<>();
        if (insertedDetails == null || insertedDetails.isEmpty()) {
            log.warn("已完成保养工单明细回查为空，跳过项目生成 | planMaintCode={}, maintInstanceId={}",
                    planMaintCodeS, instance.getMaintInstanceId());
        }
        for (DmsBillsMaintDetail detail : insertedDetails == null ? new ArrayList<DmsBillsMaintDetail>() : insertedDetails) {
            if (detail == null) {
                continue;
            }
            Long stationId = detail.getStationId();
            if (stationId == null) {
                // Why：历史数据存在列名不一致导致的部位ID取值失败，定时任务必须降级继续，避免单条脏数据拖垮整批生成。
                log.warn("保养工单明细缺少保养部位，跳过项目生成 | planMaintCode={}, maintInstanceId={}, billsMaintDetailId={}, deviceId={}",
                        planMaintCodeS, instance.getMaintInstanceId(), detail.getBillsMaintDetailId(), detail.getDeviceId());
                continue;
            }
            List<DmsBaseMaintProject> projects = dmsBillsMaintDetailMapper.selectPrjectIds(stationId);
            if (projects == null || projects.isEmpty()) {
                log.warn("保养部位未配置保养项目，跳过项目生成 | planMaintCode={}, maintInstanceId={}, billsMaintDetailId={}, stationId={}",
                        planMaintCodeS, instance.getMaintInstanceId(), detail.getBillsMaintDetailId(), stationId);
                continue;
            }
            for (DmsBaseMaintProject project : projects) {
                DmsBillsMaintDetailProject detailProject = new DmsBillsMaintDetailProject();
                detailProject.setBillsMaintDetailId(detail.getBillsMaintDetailId());
                detailProject.setMaintProjectId(project.getMaintProjectId());
                detailProject.setMaintProjectName(project.getMaintProjectName());
                detailProject.setMaintProjectDesc(project.getMaintProjectDesc());
                detailProject.setMaintProjectStatus(DmsConstants.DMS_MAINT_PROJECT_STATUS_COMPLETE); // 已完成
                detailProject.setCreateTime(now);
                projectList.add(detailProject);
            }
        }
        if (!projectList.isEmpty()) {
            dmsBillsMaintInstanceMapper.batchDmsProject(projectList);
        }

        log.info("已完成保养工单创建 | planMaintCode={}, billsMaintCode={}, maintInstanceId={}, 设备明细数={}, 项目数={}",
                planMaintCode, instance.getBillsMaintCode(), instance.getMaintInstanceId(),
                billsMaintDetails.size(), projectList.size());

        return i;
    }

    /**
     * Oracle 11/19 兼容：逐条插入明细，确保每条记录独立获取序列值。
     */
    private void insertMaintDetailsOneByOne(List<DmsBillsMaintDetail> billsMaintDetails) {
        for (DmsBillsMaintDetail detail : billsMaintDetails) {
            dmsBillsMaintInstanceMapper.insertDmsBillsMaintDetail(detail);
        }
    }
    private boolean isOracleUniqueViolation(Throwable e) {
        Throwable cursor = e;
        while (cursor != null) {
            String msg = cursor.getMessage();
            if (msg != null && msg.contains("ORA-00001")) {
                return true;
            }
            cursor = cursor.getCause();
        }
        return false;
    }

}

