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

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.mes.controller.admin.dvrepair.enums.RepairResultEnum;
import cn.iocoder.yudao.module.mes.controller.admin.dvrepair.enums.RepairStatusEnum;
import cn.iocoder.yudao.module.mes.controller.admin.dvrepair.vo.*;
import cn.iocoder.yudao.module.mes.controller.admin.ticketresults.enums.JobResultEnum;
import cn.iocoder.yudao.module.mes.dal.dataobject.dvrepair.DvRepairDO;
import cn.iocoder.yudao.module.mes.dal.dataobject.dvrepair.DvRepairLineDO;
import cn.iocoder.yudao.module.mes.dal.mysql.dvrepair.DvRepairLineMapper;
import cn.iocoder.yudao.module.mes.dal.mysql.dvrepair.DvRepairMapper;
import com.alibaba.excel.util.StringUtils;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.CollectionUtils;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.extern.slf4j.Slf4j;
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 static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;
import static cn.iocoder.yudao.module.mes.enums.ErrorCodeConstants.*;

/**
 * 设备维修记录 Service 实现类
 *
 * @author 内蒙必硕
 */
@Service
@Validated
@Slf4j
public class DvRepairServiceImpl implements DvRepairService {

    @Resource
    private DvRepairMapper dvRepairMapper;
    @Resource
    private DvRepairLineMapper dvRepairLineMapper;

    @Resource
    private AutoCodeUtil autoCodeUtil;

    @Override
    @Transactional(rollbackFor = Exception.class)
    public Long createDvRepair(DvRepairSaveReqVO createReqVO) {
        if (StringUtils.isEmpty(createReqVO.getRepairCode())) {
            createReqVO.setRepairCode(autoCodeUtil.genSerialCode("DVR_CODE",null));
        } else {
            //编码重复判断
            boolean exists = dvRepairMapper.exists(
                    Wrappers.<DvRepairDO>lambdaQuery()
                    .eq(DvRepairDO::getRepairCode, createReqVO.getRepairCode())
            );

            if (exists) {
                throw exception(DV_REPAIR_CODE_EXISTS);
            }
        }
        // 插入
        DvRepairDO dvRepair = BeanUtils.toBean(createReqVO, DvRepairDO.class);
        dvRepairMapper.insert(dvRepair);

        // 插入子表
        createDvRepairLineList(dvRepair.getId(), createReqVO.getDvRepairLines());
        // 返回
        return dvRepair.getId();
    }

    @Override
    @Transactional(rollbackFor = Exception.class)
    public void updateDvRepair(DvRepairSaveReqVO updateReqVO) {
        // 校验存在
        validateDvRepairExists(updateReqVO.getId());

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

        );

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

        // 更新
        DvRepairDO updateObj = BeanUtils.toBean(updateReqVO, DvRepairDO.class);
        dvRepairMapper.updateById(updateObj);

        // 更新子表
        updateDvRepairLineList(updateReqVO.getId(), updateReqVO.getDvRepairLines());


    }

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

    }

    private void validateDvRepairExists(Long id) {
        if (dvRepairMapper.selectById(id) == null) {
            throw exception(DV_REPAIR_NOT_EXISTS);
        }
    }

    @Override
    public DvRepairDO getDvRepair(Long id) {
        return dvRepairMapper.selectById(id);
    }

    @Override
    public PageResult<DvRepairDO> getDvRepairPage(DvRepairPageReqVO pageReqVO) {
        return dvRepairMapper.selectPage(pageReqVO);
    }

    // ==================== 子表（设备维修记录行） ====================

    @Override
    public List<DvRepairLineDO> getDvRepairLineListByRepairId(Long repairId) {
        return dvRepairLineMapper.selectListByRepairId(repairId);
    }

    @Override
    public void updateRepairLine(DvRepairLineSaveReqVO updateReqVO) {

        // 校验存在
        validateDvRepairLineExists(updateReqVO.getId());
        // 更新
        DvRepairLineDO updateObj = BeanUtils.toBean(updateReqVO, DvRepairLineDO.class);
        dvRepairLineMapper.updateById(updateObj);



    }

    @Override
    public void batchUpdateTicketResults(List<DvRepairLineSaveReqVO> updateReqVOList) {
        if (CollectionUtils.isEmpty(updateReqVOList)) {
            return;
        }

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

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

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

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

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

    @Override
    public void updateDvRepairStatus(DvRepirUpdateReqVO updateReqVO) {

        DvRepairDO dvRepairDO = dvRepairMapper.selectById(updateReqVO.getId());
        if ( dvRepairDO == null) {
            throw exception(DV_REPAIR_NOT_EXISTS);
        }
        dvRepairDO.setRequireDate(updateReqVO.getRequireDate());
        dvRepairDO.setFinishDate(updateReqVO.getFinishDate());
        dvRepairDO.setConfirmDate(updateReqVO.getConfirmDate());
        dvRepairDO.setRepairResult(updateReqVO.getRepairResult());
        dvRepairMapper.updateById(dvRepairDO);
        batchUpdateTicketResults(updateReqVO.getUpdateReqVOList());

    }

    @Override
    public List<DvRepairLineRespVO> getRepairListByDeviceId(Long deviceId, String startTime, String endTime,String ids) {

        List<DvRepairLineRespVO> dvRepairLineRespVOS = new ArrayList<>();

        LambdaQueryWrapper<DvRepairDO> wrapper = Wrappers.<DvRepairDO>lambdaQuery()
                .eq(DvRepairDO::getDeviceId, deviceId);



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

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

        List<DvRepairDO> dvRepairDOS = dvRepairMapper.selectList(wrapper);

        for (DvRepairDO dvRepairDO : dvRepairDOS) {

            LambdaQueryWrapper<DvRepairLineDO> dvRepairLineDOLambdaQueryWrapper = Wrappers.<DvRepairLineDO>lambdaQuery()
                    .eq(DvRepairLineDO::getRepairId, dvRepairDO.getId())
                    .orderByDesc(DvRepairLineDO::getCreateTime);

            List<DvRepairLineDO> dvRepairLineDOS = dvRepairLineMapper.selectList(dvRepairLineDOLambdaQueryWrapper);

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

        // 在最终结果上过滤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()) {
                dvRepairLineRespVOS = dvRepairLineRespVOS.stream()
                        .filter(vo -> idList.contains(vo.getId()))  // 假设vo有getId()方法
                        .collect(Collectors.toList());
            }
        }


        return dvRepairLineRespVOS;
    }

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

    }

    @Override
    public List<DvRepairDO> getDvRepairDOListByStatus() {
        return dvRepairMapper.selectList(Wrappers.<DvRepairDO>lambdaQuery()
                .eq(DvRepairDO::getRepairStatus, 0));

    }

    @Override
    public void selectCountDeviceRepair(EventStatisticsVO eventStatisticsVO) {

        //设备待维修数量
        int count = dvRepairMapper.selectCount(Wrappers.<DvRepairDO>lambdaQuery()
                .eq(DvRepairDO::getStatus, RepairStatusEnum.PENDING.getCode())).intValue();

        eventStatisticsVO.setDeviceRepair(count);
    }

    @Override
    public List<DvRepairDO> getList() {
        return dvRepairMapper.selectList();
    }


    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<DvRepairLineSaveReqVO> updateReqVOList) {

        if (CollectionUtils.isEmpty(updateReqVOList)) {
            return;
        }

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

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

        } else {
            dvRepairDO.setRepairStatus(JobResultEnum.PASS.getCode());
        }
        dvRepairMapper.updateById(dvRepairDO);

    }

    private void validateBatchUpdateData(List<DvRepairLineSaveReqVO> updateReqVOList) {


        if (CollectionUtils.isEmpty(updateReqVOList)) {
            return;
        }

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

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

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

            idSet.add(vo.getId());

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

    private void validateDvRepairLineExists(Long id) {
        if (dvRepairLineMapper.selectById(id) == null) {
            throw exception(DV_REPAIR_LINE_NOT_EXISTS);
        }
    }

    private void createDvRepairLineList(Long repairId, List<DvRepairLineDO> list) {
        list.forEach(o -> o.setRepairId(repairId));
        dvRepairLineMapper.insertBatch(list);
    }

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

    private void deleteDvRepairLineByRepairId(Long repairId) {
        dvRepairLineMapper.deleteByRepairId(repairId);
    }

}