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

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.ObjectUtil;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.cf.imes.framework.common.exception.ServiceException;
import com.cf.imes.framework.mybatis.core.query.LambdaUpdateWrapperX;
import com.cf.imes.module.executor.dal.dataobject.goods.GoodsDO;
import com.cf.imes.module.executor.dal.dataobject.goods.OrderGoodsPlateNumAndAreaDO;
import com.cf.imes.module.executor.dal.dataobject.order.OrderDO;
import com.cf.imes.module.executor.dal.dataobject.order.OrderPackNumDO;
import com.cf.imes.module.executor.dal.dataobject.order.OrderPlateNumAndAreaDO;
import com.cf.imes.module.executor.dal.dataobject.orderBody.OrderBodyDO;
import com.cf.imes.module.executor.dal.dataobject.orderBody.OrderBodyPlateNumDO;
import com.cf.imes.module.executor.dal.mysql.goods.GoodsMapper;
import com.cf.imes.module.executor.dal.mysql.order.OrderMapper;
import com.cf.imes.module.executor.dal.mysql.orderBody.OrderBodyMapper;
import com.cf.imes.module.executor.enums.ErrorCodeConstants;
import com.cf.imes.module.executor.enums.OrderStatusEnum;
import jakarta.annotation.Resource;
import org.springframework.stereotype.Service;

import java.math.BigDecimal;
import java.util.Collection;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * 订单信息版本控制服务实现类 ServiceImpl
 *
 * @author Gqr
 * @since 2026/4/14 14:17
 */
@Service
public class OrderInfoVersionControlServiceImpl implements OrderInfoVersionControlService {
    @Resource
    private OrderMapper orderMapper;

    @Resource
    private OrderBodyMapper orderBodyMapper;

    @Resource
    private GoodsMapper goodsMapper;

    @Override
    public void updateOrderPlateNumAndArea(OrderDO orderDO, Boolean delete) {
        Long orderId = orderDO.getId();
        // 重新计算订单数量
        // 统计每个orders下的板件数量和面积，更新到orders中
        OrderPlateNumAndAreaDO orderPlateNumAndAreaDO = orderMapper.selectPlateNumAndArea(orderId, !delete);

        // 当前订单下排单的板件数量
        Integer num = orderPlateNumAndAreaDO.getNum();

        int version = orderDO.getVersion();
        LambdaUpdateWrapper<OrderDO> updateWrapper = new LambdaUpdateWrapperX<OrderDO>()
                .eq(OrderDO::getId, orderId)
                .eq(OrderDO::getVersion, version)
                .setIfPresent(OrderDO::getStatus, num == 0 ? OrderStatusEnum.EMPTY.getStatus() : OrderStatusEnum.NEW_ORDER.getStatus())
                .set(OrderDO::getArea, orderPlateNumAndAreaDO.getArea())
                .set(OrderDO::getPlateNum, num)
                .set(OrderDO::getVersion, version + 1);
        int update = orderMapper.update(updateWrapper);
        if (update == 0) {
            throw new ServiceException(com.cf.imes.module.executor.enums.ErrorCodeConstants.ORDER_PLATE_UPDATE_CONCURRENCY_ERROR, orderId);
        }
    }

    @Override
    public void updateOrderBodyPlateNum(Collection<Long> orderBodyIds, Boolean delete) {
        // 查询删除涉及的柜体
        Map<Long, OrderBodyDO> bodyMap = orderBodyMapper.selectByIds(orderBodyIds)
                .stream()
                .collect(Collectors.toMap(OrderBodyDO::getId, Function.identity()));

        // 统计删除涉及的柜体下的数量和面积、更新到order_body
        Map<Long, OrderBodyPlateNumDO> bodyStatMap = orderBodyMapper.selectPlateNumAndArea(orderBodyIds, !delete)
                .stream()
                .collect(Collectors.toMap(
                        OrderBodyPlateNumDO::getOrderBodyId,
                        Function.identity()
                ));
        for (Map.Entry<Long, OrderBodyPlateNumDO> entry : bodyStatMap.entrySet()) {
            Long orderBodyId = entry.getKey();

            OrderBodyDO orderBodyDO = bodyMap.get(orderBodyId);
            int version = orderBodyDO.getVersion();
            OrderBodyPlateNumDO stat =
                    bodyStatMap.getOrDefault(orderBodyId,
                            new OrderBodyPlateNumDO(orderBodyId, 0));

            int update = orderBodyMapper.update(new LambdaUpdateWrapper<OrderBodyDO>()
                    .eq(OrderBodyDO::getId, orderBodyId)
                    .eq(OrderBodyDO::getVersion, version)
                    .set(OrderBodyDO::getPlateNum, stat.getNum())
                    .set(OrderBodyDO::getVersion, version + 1));

            if (update == 0) {
                throw new ServiceException(ErrorCodeConstants.BODY_PLATE_UPDATE_CONCURRENCY_ERROR, orderBodyId);
            }
        }
    }

    @Override
    public void updateOrderGoodsPlateNumAndArea(Collection<Long> orderGoodsIds, Boolean delete) {
        // 查询删除涉及的order_goods
        Map<Long, GoodsDO> goodsMap =
                goodsMapper.selectByIds(orderGoodsIds)
                        .stream()
                        .collect(Collectors.toMap(GoodsDO::getId, Function.identity()));

        // 统计删除涉及的order_goods下的数量和面积、更新到order_goods
        Map<Long, OrderGoodsPlateNumAndAreaDO> goodStatMap =
                goodsMapper.selectPlateNumAndArea(orderGoodsIds, !delete)
                        .stream()
                        .collect(Collectors.toMap(
                                OrderGoodsPlateNumAndAreaDO::getOrderGoodsId,
                                Function.identity()
                        ));

        for (Long orderGoodsId : orderGoodsIds) {

            GoodsDO goodsDO = goodsMap.get(orderGoodsId);

            OrderGoodsPlateNumAndAreaDO stat =
                    goodStatMap.getOrDefault(orderGoodsId,
                            new OrderGoodsPlateNumAndAreaDO(orderGoodsId, 0, BigDecimal.ZERO));

            int version = goodsDO.getVersion();
            int update = goodsMapper.update(new LambdaUpdateWrapper<GoodsDO>()
                    .eq(GoodsDO::getId, orderGoodsId)
                    .eq(GoodsDO::getVersion, version)
                    .set(GoodsDO::getArea, stat.getArea())
                    .set(GoodsDO::getPlateNum, stat.getNum())
                    .set(GoodsDO::getVersion, version + 1));

            if (update == 0) {
                throw new ServiceException(ErrorCodeConstants.GOODS_PLATE_UPDATE_CONCURRENCY_ERROR, orderGoodsId);
            }
        }
    }

    @Override
    public void updateOrderPackNum(List<OrderDO> orderDOS) {
        List<Long> orderIds = orderDOS.stream().map(OrderDO::getId).collect(Collectors.toList());
        Map<Long, OrderDO> orderMap = orderDOS.stream()
                .collect(Collectors.toMap(OrderDO::getId, Function.identity()));

        List<OrderPackNumDO> orderPackPlateNumDOS = orderMapper.selectPackPlateNum(orderIds);
//        List<OrderPackNumDO> orderPackPartsNumDOS = orderMapper.selectPackPartsNum(orderIds);
//        Map<Long, Integer> orderPackPartsNumMap = new HashMap<>();
//        if (CollUtil.isNotEmpty(orderPackPartsNumDOS)) {
//            orderPackPartsNumMap = orderPackPartsNumDOS.stream()
//                    .collect(Collectors.toMap(OrderPackNumDO::getOrderId, OrderPackNumDO::getPartsNum));
//        }

        for (OrderPackNumDO orderPackPlateNumDO : orderPackPlateNumDOS) {
            Long orderId = orderPackPlateNumDO.getOrderId();
            // 当前订单下已打包板件
            Integer plateNum = orderPackPlateNumDO.getPlateNum();
//            // 当前订单下已打包配件
//            Integer partsNum = orderPackPartsNumMap.getOrDefault(orderId, 0);

            OrderDO orderDO = orderMap.get(orderId);

            if (ObjectUtil.isNull(orderDO)) {
                continue;
            }
            int version = orderDO.getVersion();
            // 更新数量
            LambdaUpdateWrapper<OrderDO> updateWrapper = new LambdaUpdateWrapperX<OrderDO>()
                    .eq(OrderDO::getId, orderId)
                    .eq(OrderDO::getVersion, version)
                    .set(OrderDO::getPackedPlatesCount, plateNum)
//                    .set(OrderDO::getPackedPartsCount, partsNum)
                    .set(OrderDO::getVersion, version + 1);
            int update = orderMapper.update(updateWrapper);
            if (update == 0) {
                throw new ServiceException(com.cf.imes.module.executor.enums.ErrorCodeConstants.ORDER_PLATE_UPDATE_CONCURRENCY_ERROR, orderId);
            }
        }
    }
}
