package com.cf.imes.module.executor.service.customplatenorule;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import com.alibaba.fastjson.JSON;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.cf.imes.framework.common.util.json.JsonUtils;
import com.cf.imes.framework.organ.core.context.OrganContextHolder;
import com.cf.imes.module.executor.api.customplateno.dto.CustomPlateNoRuleDTO;
import com.cf.imes.module.executor.dal.dataobject.order.OrderDO;
import com.cf.imes.module.executor.dal.dataobject.plate.PlateDO;
import com.cf.imes.module.executor.dal.mysql.order.OrderMapper;
import com.cf.imes.module.executor.service.customplateno.vo.CustomPlateNoGenerateConfigVO;
import com.cf.imes.module.executor.service.customplateno.vo.CustomPlateNoRuleVO;
import com.cf.imes.module.executor.service.customplateno.vo.OrderCustomPlateNoSeqRoomVO;
import com.cf.imes.module.executor.service.customplateno.vo.OrderCustomPlateNoSeqVO;
import com.cf.imes.module.system.api.customplateno.dto.CustomPlateNoSeqDTO;
import com.cf.imes.module.system.enums.customplateno.CustomPlateNoRuleCodeEnum;
import org.springframework.stereotype.Service;

import jakarta.annotation.Resource;
import java.util.ArrayList;
import java.util.List;
import java.util.Optional;

/**
 * 房间序号生成规则服务实现类
 *
 * @author Gqr
 * @since 2024/11/19 13:41
 */
@Service("roomNoGenerateRuleService")
public class RoomNoGenerateRuleServiceImpl implements CustomPlateNoGenerateRuleService {
    @Resource
    private OrderMapper orderMapper;

    @Override
    public boolean match(String ruleCode) {
        return ObjectUtil.equal(CustomPlateNoRuleCodeEnum.ROOMNO.getRuleCode(), ruleCode);
    }

    /**
     * 初始化生成所需配置
     *
     * @param generateConfigVO
     */
    private static void initConfig(CustomPlateNoGenerateConfigVO generateConfigVO) {
        OrderCustomPlateNoSeqVO orderCustomPlateNoSeqVO = generateConfigVO.getOrderCustomPlateNoSeqVO();
        if (ObjectUtil.isNull(orderCustomPlateNoSeqVO)) {
            orderCustomPlateNoSeqVO = new OrderCustomPlateNoSeqVO();
            generateConfigVO.setOrderCustomPlateNoSeqVO(orderCustomPlateNoSeqVO);
        }
        List<OrderCustomPlateNoSeqRoomVO> rooms = orderCustomPlateNoSeqVO.getRooms();
        if (CollUtil.isEmpty(rooms)) {
            rooms = new ArrayList<>();
            orderCustomPlateNoSeqVO.setRooms(rooms);
        }
    }

    @Override
    public CustomPlateNoGenerateConfigVO generateNo(Long orderId, CustomPlateNoRuleVO plateNoRule, CustomPlateNoGenerateConfigVO generateConfig, PlateDO plateDO, boolean firstPlate) {
        Integer incrementStep = plateNoRule.getIncrementStep();
        Integer initValue = plateNoRule.getInitValue() - incrementStep;
        // 初始化配置
        initConfig(generateConfig);
        // 生产单下的序号
        OrderCustomPlateNoSeqVO orderCustomPlateNoSeqVO = generateConfig.getOrderCustomPlateNoSeqVO();
        // 机构下的自定义板编号序号
        CustomPlateNoSeqDTO orgCustomPlateNoSeqRespDTO = generateConfig.getOrgCustomPlateNoSeqRespDTO();
        // 生产单下房间序号
        Integer orderRoomNoSeq = Optional.ofNullable(orderCustomPlateNoSeqVO.getRoomNoSeq()).orElse(initValue);
        // 生产单序号下的的房间序号列表
        List<OrderCustomPlateNoSeqRoomVO> rooms = orderCustomPlateNoSeqVO.getRooms();
        // 上次导入的生产单号
        Long lastOrderNo = orgCustomPlateNoSeqRespDTO.getLastOrderNo();
        if (firstPlate && (ObjectUtil.isNull(lastOrderNo) || ObjectUtil.notEqual(orderId, lastOrderNo))) {
            // 跨单复位到初始值
            orderRoomNoSeq = initValue;
        }

        String roomName = plateDO.getRoomName();
        // 根据房间名获取生产单下序号json中的房间下的柜体序号
        OrderCustomPlateNoSeqRoomVO roomSeqVo = getRoomSeqVOByRoomName(roomName, rooms);
        // 获取当前房间序号值
        Integer roomNoSeq = Optional.ofNullable(roomSeqVo).map(OrderCustomPlateNoSeqRoomVO::getRoomNoSeq).orElse(null);
        if (roomSeqVo == null) {
            // 房间为空，新建房间，取生产单下房间序号
            roomSeqVo = OrderCustomPlateNoSeqRoomVO.builder()
                    .roomName(roomName)
                    .bodys(new ArrayList<>())
                    .build();
            rooms.add(roomSeqVo);
            // 累加步长
            roomNoSeq = orderRoomNoSeq + incrementStep;
            // 累加后的值同步到当前生产单序号中，生产单下房间序号累加到多少了
            orderCustomPlateNoSeqVO.setRoomNoSeq(roomNoSeq);
        } else if (roomNoSeq == null) {
            // 房间下序号为空，取生产单下房间序号
            // 累加步长
            roomNoSeq = orderRoomNoSeq + incrementStep;
            // 累加后的值同步到当前生产单序号中，生产单下房间序号累加到多少了
            orderCustomPlateNoSeqVO.setRoomNoSeq(roomNoSeq);
        }

        // 补零
        String noPartAfterFillZero = fillZero(roomNoSeq, plateNoRule);
        plateDO.getCustomPlateNoBuilder().append(noPartAfterFillZero);
        // 累加后同步到json：房间下累加到多少了
        roomSeqVo.setRoomNoSeq(roomNoSeq);

        return generateConfig;
    }

    @Override
    public void reset(CustomPlateNoRuleDTO ruleDTO) {
        // 查询所有使用当前配置id的生产单列表
        Long configId = ruleDTO.getConfigId();
        List<OrderDO> orderDOS = orderMapper.selectList(
                new LambdaQueryWrapper<OrderDO>().eq(OrderDO::getCustomPlatenoConfigId, configId).eq(OrderDO::getOrganId, OrganContextHolder.getOrganId()));

        // 更新生产单的序号
        for (OrderDO orderDO : orderDOS) {
            OrderCustomPlateNoSeqVO orderCustomPlateNoSeqVO = JSON.parseObject(orderDO.getCustomPlatenoSeq(), OrderCustomPlateNoSeqVO.class);
            if (ObjectUtil.isNotNull(orderCustomPlateNoSeqVO)) {
                orderCustomPlateNoSeqVO.setRoomNoSeq(null);
                orderMapper.update(new LambdaUpdateWrapper<OrderDO>().eq(OrderDO::getId, orderDO.getId()).set(OrderDO::getCustomPlatenoSeq, JsonUtils.zipString(JSON.toJSONString(orderCustomPlateNoSeqVO))));
            }
        }
    }

    /**
     * 根据房间名从生产单序号json中获取房间序号列表
     *
     * @param roomName
     * @param roomVOList
     * @return
     */
    private OrderCustomPlateNoSeqRoomVO getRoomSeqVOByRoomName(String roomName, List<OrderCustomPlateNoSeqRoomVO> roomVOList) {
        return roomVOList.stream().filter(roomVO -> ObjectUtil.equal(roomName, roomVO.getRoomName())).findAny().orElse(null);
    }
}
