package cn.iocoder.yudao.module.mes.service.moldrepair;

import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.common.util.object.BeanUtils;
import cn.iocoder.yudao.module.erp.controller.admin.autocode.util.AutoCodeUtil;
import cn.iocoder.yudao.module.mes.controller.admin.dashboard.vo.dashboard.EventStatisticsVO;
import cn.iocoder.yudao.module.common.controller.admin.moldrepair.enums.RepairResultEnum;
import cn.iocoder.yudao.module.common.controller.admin.moldrepair.vo.MoldRepairLineRespVO;
import cn.iocoder.yudao.module.common.controller.admin.moldrepair.vo.MoldRepairLineSaveReqVO;
import cn.iocoder.yudao.module.common.controller.admin.moldrepair.vo.MoldRepairUpdateReqVO;
import cn.iocoder.yudao.module.common.controller.admin.moldrepair.vo.MoldRepairPageReqVO;
import cn.iocoder.yudao.module.common.controller.admin.moldrepair.vo.MoldRepairSaveReqVO;
import cn.iocoder.yudao.module.mes.controller.admin.ticketresults.enums.JobResultEnum;
import cn.iocoder.yudao.module.common.dal.dataobject.moldrepair.MoldRepairDO;
import cn.iocoder.yudao.module.common.dal.dataobject.moldrepair.MoldRepairLineDO;
import cn.iocoder.yudao.module.common.dal.mysql.moldrepair.MoldRepairLineMapper;
import cn.iocoder.yudao.module.common.dal.mysql.moldrepair.MoldRepairMapper;
import com.alibaba.excel.util.StringUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import java.time.LocalDate;
import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.*;
import java.util.stream.Collectors;

import lombok.extern.slf4j.Slf4j;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*;

import org.springframework.util.CollectionUtils;
import cn.iocoder.yudao.framework.common.exception.ServiceException;


/**
 * 模具维修记录 Service 实现类
 *
 * @author 内蒙必硕
 */
@Slf4j
@Service
@Validated
public class MoldRepairServiceImpl implements MoldRepairService {

    @Resource
    private MoldRepairMapper moldRepairMapper;
    @Resource
    private MoldRepairLineMapper moldRepairLineMapper;

    @Resource
    private AutoCodeUtil autoCodeUtil;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long createMoldRepair(MoldRepairSaveReqVO createReqVO) {
        if (StringUtils.isEmpty(createReqVO.getRepairCode())) {
            createReqVO.setRepairCode(autoCodeUtil.genSerialCode("MR_CODE",null));
        } else {
            //编码重复判断
            Long count = moldRepairMapper.selectCount(new LambdaQueryWrapper<MoldRepairDO>()
                    .eq(MoldRepairDO::getRepairCode, createReqVO.getRepairCode())
            );

            if (count > 0) {
                throw exception(MOLD_REPAIR_CODE_EXISTS);
            }
        }
        // 插入
        MoldRepairDO moldRepair = BeanUtils.toBean(createReqVO, MoldRepairDO.class);
        moldRepairMapper.insert(moldRepair);

        // 插入子表
        createMoldRepairLineList(moldRepair.getId(), createReqVO.getMoldRepairLines());
        // 返回
        return moldRepair.getId();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateMoldRepair(MoldRepairSaveReqVO updateReqVO) {
        // 校验存在
        validateMoldRepairExists(updateReqVO.getId());

        //编码重复判断
        Long count = moldRepairMapper.selectCount(new LambdaQueryWrapper<MoldRepairDO>()
                .eq(MoldRepairDO::getRepairCode, updateReqVO.getRepairCode())
                .ne(MoldRepairDO::getId, updateReqVO.getId())

        );

        if (count > 0) {
            throw exception(MOLD_REPAIR_CODE_EXISTS);
        }

        // 更新
        MoldRepairDO updateObj = BeanUtils.toBean(updateReqVO, MoldRepairDO.class);
        moldRepairMapper.updateById(updateObj);

        // 更新子表
        updateMoldRepairLineList(updateReqVO.getId(), updateReqVO.getMoldRepairLines());
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void deleteMoldRepair(List<Long> idList) {
        for (Long id : idList) {
            // 校验存在
            validateMoldRepairExists(id);
            // 删除
            moldRepairMapper.deleteById(id);
            // 删除子表
            deleteMoldRepairLineByRepairId(id);
        }

    }

    private void validateMoldRepairExists(Long id) {
        if (moldRepairMapper.selectById(id) == null) {
            throw exception(MOLD_REPAIR_NOT_EXISTS);
        }
    }

    @Override
    public MoldRepairDO getMoldRepair(Long id) {
        return moldRepairMapper.selectById(id);
    }

    @Override
    public PageResult<MoldRepairDO> getMoldRepairPage(MoldRepairPageReqVO pageReqVO) {
        return moldRepairMapper.selectPage(pageReqVO);
    }

    // ==================== 子表（模具维修记录行） ====================

    @Override
    public List<MoldRepairLineDO> getMoldRepairLineListByRepairId(Long repairId) {
        return moldRepairLineMapper.selectListByRepairId(repairId);
    }

//    private void createMoldRepairLineList(Long repairId, List<MoldRepairLineDO> list) {
//        list.forEach(o -> o.setRepairId(repairId));
//        moldRepairLineMapper.insertBatch(list);
//    }
    private void createMoldRepairLineList(Long repairId, List<MoldRepairLineDO> list) {
        // 2. 校验维修单ID非空
        if (repairId == null) {
            log.error("创建维修单行数据失败：维修单ID为null");
            throw new ServiceException(MOLD_REPAIR_ID_NULL);
        }

        // 3. 校验列表非空（核心：解决第125行空指针）
        if (CollectionUtils.isEmpty(list)) {
            log.warn("维修单{}暂无行数据，跳过行记录创建", repairId);
            return;
        }

        // 4. 遍历列表，校验每个元素非空并设置repairId
        for (MoldRepairLineDO lineDO : list) {
            if (lineDO == null) {
                log.warn("维修单{}发现空的行数据，跳过处理", repairId);
                continue; // 跳过空元素，不影响其他数据
            }
            lineDO.setRepairId(repairId); // 设置主表关联ID
        }

        // 5. 校验mapper是否注入（兜底）
        if (moldRepairLineMapper == null) {
            log.error("创建维修单行数据失败：moldRepairLineMapper未注入");
            throw new ServiceException(MOLD_REPAIR_MAPPER_NULL);
        }

        // 6. 批量插入
        moldRepairLineMapper.insertBatch(list);
        log.info("维修单{}成功创建{}条行数据", repairId, list.size());
    }

    private void updateMoldRepairLineList(Long repairId, List<MoldRepairLineDO> list) {
        deleteMoldRepairLineByRepairId(repairId);
		list.forEach(o -> o.setId(null).setUpdater(null).setUpdateTime(null)); // 解决更新情况下：1）id 冲突；2）updateTime 不更新
        createMoldRepairLineList(repairId, list);
    }

    private void deleteMoldRepairLineByRepairId(Long repairId) {
        moldRepairLineMapper.deleteByRepairId(repairId);
    }




    @Override
    public void updateRepairLine(MoldRepairLineSaveReqVO updateReqVO) {

        // 校验存在
        validateMoldRepairLineExists(updateReqVO.getId());
        // 更新
        MoldRepairLineDO updateObj = BeanUtils.toBean(updateReqVO, MoldRepairLineDO.class);
        moldRepairLineMapper.updateById(updateObj);



    }

    @Override
    public void batchUpdateTicketResults(List<MoldRepairLineSaveReqVO> updateReqVOList) {
        if (com.baomidou.mybatisplus.core.toolkit.CollectionUtils.isEmpty(updateReqVOList)) {
            return;
        }

        // 1. 数据验证
        validateBatchUpdateData(updateReqVOList);

        // 2. 批量更新
        List<MoldRepairLineDO> updateList = new ArrayList<>();
        LocalDateTime now = LocalDateTime.now();

        for (MoldRepairLineSaveReqVO vo : updateReqVOList) {
            // 转换为DO
            MoldRepairLineDO updateDO = BeanUtils.toBean(vo, MoldRepairLineDO.class);
            updateDO.setUpdateTime(now);
            updateList.add(updateDO);
        }

        // 3. 执行批量更新
        moldRepairLineMapper.updateBatch(updateList);

        //4. 判断是否全部已检验
        handleInspectionResult(updateReqVOList);
    }

    @Override
    public void updateMoldRepairStatus(MoldRepairUpdateReqVO updateReqVO) {

        MoldRepairDO moldRepairDO = moldRepairMapper.selectById(updateReqVO.getId());
        if ( moldRepairDO == null) {
            throw exception(MOLD_REPAIR_NOT_EXISTS);
        }
        moldRepairDO.setRequireDate(updateReqVO.getRequireDate());
        moldRepairDO.setFinishDate(updateReqVO.getFinishDate());
        moldRepairDO.setConfirmDate(updateReqVO.getConfirmDate());
        moldRepairDO.setRepairResult(updateReqVO.getRepairResult());
        moldRepairMapper.updateById(moldRepairDO);
        batchUpdateTicketResults(updateReqVO.getUpdateReqVOList());

    }

    @Override
    public List<MoldRepairLineRespVO> getRepairListByMoldId(Long moldId, String startTime, String endTime, String ids) {

        List<MoldRepairLineRespVO> moldRepairLineRespVOS = new ArrayList<>();

        LambdaQueryWrapper<MoldRepairDO> wrapper = Wrappers.<MoldRepairDO>lambdaQuery()
                .eq(MoldRepairDO::getMoldId, moldId);



        // 处理开始时间
        if (StringUtils.isNotBlank(startTime)) {
            try {
                LocalDateTime parseToLocalDateTime = parseToLocalDateTime(startTime);
                wrapper.ge(MoldRepairDO::getFinishDate, parseToLocalDateTime);
            } catch (Exception e) {
                log.error("开始时间格式错误: {}, 异常: {}", startTime, e.getMessage(), e);
            }
        }

        // 处理结束时间
        if (StringUtils.isNotBlank(endTime)) {
            try {
                LocalDateTime parseToLocalDateTime = parseToLocalDateTime(endTime);
                wrapper.le(MoldRepairDO::getFinishDate, parseToLocalDateTime);
            } catch (Exception e) {
                log.error("结束时间格式错误: {}, 异常: {}", startTime, e.getMessage(), e);
            }
        }

        List<MoldRepairDO> moldRepairDOS = moldRepairMapper.selectList(wrapper);

        for (MoldRepairDO moldRepairDO : moldRepairDOS) {

            LambdaQueryWrapper<MoldRepairLineDO> moldRepairLineDOLambdaQueryWrapper = Wrappers.<MoldRepairLineDO>lambdaQuery()
                    .eq(MoldRepairLineDO::getRepairId, moldRepairDO.getId())
                    .orderByDesc(MoldRepairLineDO::getCreateTime);

            List<MoldRepairLineDO> moldRepairLineDOS = moldRepairLineMapper.selectList(moldRepairLineDOLambdaQueryWrapper);

            if (!moldRepairLineDOS.isEmpty()) {
                List<MoldRepairLineRespVO> moldRepairLineRespVOList = moldRepairLineDOS.stream()
                        .map(doItem -> {
                            MoldRepairLineRespVO vo = new MoldRepairLineRespVO();
                            BeanUtils.copyProperties(doItem, vo);
                            vo.setRepairCode(moldRepairDO.getRepairCode());
                            vo.setRepairName(moldRepairDO.getRepairName());
                            vo.setFinishDate(moldRepairDO.getFinishDate());
                            // 设置维修结果描述
                            vo.setRepairResult(RepairResultEnum.getDescByCode(doItem.getResult()));
                            return vo;
                        })
                        .collect(Collectors.toList());
                moldRepairLineRespVOS.addAll(moldRepairLineRespVOList);
            }
        }

        // 在最终结果上过滤ids
        if (StringUtils.isNotBlank(ids)) {
            List<Long> idList = Arrays.stream(ids.split(","))
                    .map(String::trim)
                    .filter(StringUtils::isNotBlank)
                    .map(Long::valueOf)
                    .collect(Collectors.toList());
            if (!idList.isEmpty()) {
                moldRepairLineRespVOS = moldRepairLineRespVOS.stream()
                        .filter(vo -> idList.contains(vo.getId()))  // 假设vo有getId()方法
                        .collect(Collectors.toList());
            }
        }


        return moldRepairLineRespVOS;
    }


    private LocalDateTime parseToLocalDateTime(String timeStr) {
        if (StringUtils.isBlank(timeStr)) {
            return null;
        }

        timeStr = timeStr.trim();

        try {
            // 尝试解析 yyyy-MM-dd HH:mm:ss
            if (timeStr.length() == 19) {
                return LocalDateTime.parse(timeStr,
                        DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
            }
            // 尝试解析 yyyy-MM-dd
            else if (timeStr.length() == 10) {
                return LocalDate.parse(timeStr,
                                DateTimeFormatter.ofPattern("yyyy-MM-dd"))
                        .atStartOfDay();
            }
            // 尝试解析 yyyy/MM/dd HH:mm:ss
            else if (timeStr.contains("/")) {
                return LocalDateTime.parse(timeStr.replace("/", "-"),
                        DateTimeFormatter.ofPattern("yyyy-MM-dd HH:mm:ss"));
            }
            // 尝试ISO格式
            else {
                return LocalDateTime.parse(timeStr,
                        DateTimeFormatter.ISO_LOCAL_DATE_TIME);
            }
        } catch (Exception e) {
            throw new IllegalArgumentException("时间格式不支持: " + timeStr, e);
        }
    }
    private void handleInspectionResult(List<MoldRepairLineSaveReqVO> updateReqVOList) {

        if (com.baomidou.mybatisplus.core.toolkit.CollectionUtils.isEmpty(updateReqVOList)) {
            return;
        }

        // 检查是否有未填写的
        boolean hasPending = updateReqVOList.stream()
                .anyMatch(vo -> vo.getResult() == null || vo.getResult().equals(JobResultEnum.PENDING.getCode()));

        if (hasPending) {
            return;
        }
        MoldRepairDO moldRepairDO = moldRepairMapper.selectById(updateReqVOList.get(0).getRepairId());
        if (moldRepairDO == null ){
            throw exception(MOLD_REPAIR_NOT_EXISTS);
        }
        //设置为已完成
        moldRepairDO.setStatus(JobResultEnum.PASS.getCode());
        // 检查是否有不通过的
        boolean hasFail = updateReqVOList.stream()
                .anyMatch(vo -> vo.getResult() != null && vo.getResult().equals(JobResultEnum.FAIL.getCode()));
        if (hasFail) {
            moldRepairDO.setRepairStatus(JobResultEnum.FAIL.getCode());

        } else {
            moldRepairDO.setRepairStatus(JobResultEnum.PASS.getCode());
        }
        moldRepairMapper.updateById(moldRepairDO);

    }

    private void validateBatchUpdateData(List<MoldRepairLineSaveReqVO> updateReqVOList) {


        if (com.baomidou.mybatisplus.core.toolkit.CollectionUtils.isEmpty(updateReqVOList)) {
            return;
        }

        Set<Long> idSet = new HashSet<>();

        for (int i = 0; i < updateReqVOList.size(); i++) {
            MoldRepairLineSaveReqVO vo = updateReqVOList.get(i);

            // 验证ID不能为空
            if (vo.getId() == null) {
                throw exception(MOLD_REPAIR_LINE_ID_NOT_EXISTS);
            }

            idSet.add(vo.getId());

            // 调用单个验证逻辑
            validateMoldRepairLineExists(vo.getId());
        }
    }

    private void validateMoldRepairLineExists(Long id) {
        if (moldRepairLineMapper.selectById(id) == null) {
            throw exception(MOLD_REPAIR_LINE_NOT_EXISTS);
        }
    }

    @Override
    public Long getRepairListCountByRepairStatus() {
        return moldRepairMapper.selectCount(Wrappers.<MoldRepairDO>lambdaQuery()
                .eq(MoldRepairDO::getRepairStatus, 0));

    }

    @Override
    public List<MoldRepairDO> getMoldRepairDOListByStatus() {
        return moldRepairMapper.selectList(Wrappers.<MoldRepairDO>lambdaQuery()
                .eq(MoldRepairDO::getRepairStatus, 0));

    }

    @Override
    public void selectCountMoldRepair(EventStatisticsVO eventStatisticsVO) {
        //未完成维修单
        int intValue = moldRepairMapper.selectCount(Wrappers.<MoldRepairDO>lambdaQuery()
                .eq(MoldRepairDO::getStatus, 0)).intValue();
        eventStatisticsVO.setMoldRepair(intValue);
    }

    @Override
    public List<MoldRepairDO> getList() {
        return moldRepairMapper.selectList();
    }
}