package cn.iocoder.yudao.module.order.service.order.impl;

import cn.hutool.core.collection.CollectionUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.i18n.core.I18nMessage;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.framework.mybatis.core.service.AbstractService;
import cn.iocoder.yudao.framework.mybatis.core.vo.PageVO;
import cn.iocoder.yudao.module.depository.dal.dataobject.warehouse.WarehouseAreaDO;
import cn.iocoder.yudao.module.depository.dal.dataobject.warehouse.WarehouseAreaPositionDO;
import cn.iocoder.yudao.module.depository.dal.mysql.warehouse.WarehouseAreaMapper;
import cn.iocoder.yudao.module.depository.dal.mysql.warehouse.WarehouseAreaPositionMapper;
import cn.iocoder.yudao.module.order.convert.orderItem.OrderItemConvert;
import cn.iocoder.yudao.module.order.convert.orderLocation.OrderLocationConvert;
import cn.iocoder.yudao.module.order.dal.dataobject.orderItem.OrderItemDO;
import cn.iocoder.yudao.module.order.dal.dataobject.orderLocation.OrderLocationDO;
import cn.iocoder.yudao.module.order.dal.mysql.approval.OrderApprovalMapper;
import cn.iocoder.yudao.module.order.dal.mysql.orderItem.OrderItemMapper;
import cn.iocoder.yudao.module.order.dal.mysql.orderLocation.OrderLocationMapper;
import cn.iocoder.yudao.module.order.service.order.OrderItemService;
import cn.iocoder.yudao.module.order.vo.order.WarehouseInInfoVO;
import cn.iocoder.yudao.module.order.vo.orderItem.*;
import cn.iocoder.yudao.module.order.vo.orderLocation.OrderLocationBackVO;
import cn.iocoder.yudao.module.order.vo.orderLocation.OrderLocationMergeVO;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;

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.order.enums.ErrorCodeConstants.ORDER_ITEM_NOT_EXISTS;

/**
 * 订单项 Service 实现类
 *
 * @author 系统管理员
 */
@Service
@Validated
public class OrderItemServiceImpl extends AbstractService<OrderItemMapper, OrderItemDO> implements OrderItemService {

    @Autowired
    private OrderItemMapper orderItemMapper;
    @Autowired
    private OrderApprovalMapper orderApprovalMapper;

    @Autowired
    private OrderLocationMapper orderLocationMapper;


    @Autowired
    private WarehouseAreaMapper warehouseAreaMapper;

    @Autowired
    private WarehouseAreaPositionMapper warehouseAreaPositionMapper;

    @Override
    public Long createOrderItem(OrderItemCreateReqVO createReqVO) {
        // 插入
        OrderItemDO orderItem = OrderItemConvert.INSTANCE.convert(createReqVO);
        orderItemMapper.insert(orderItem);
        // 返回
        return orderItem.getOrderItemId();
    }

    @Override
    public void updateOrderItem(OrderItemUpdateReqVO updateReqVO) {
        // 校验存在
        this.validateOrderItemExists(updateReqVO.getOrderItemId());
        // 更新
        OrderItemDO updateObj = OrderItemConvert.INSTANCE.convert(updateReqVO);
        orderItemMapper.updateById(updateObj);
    }

    @Override
    public void updateOrderItemType(Long orderItemId, Integer orderItemType) {
        OrderItemDO orderItemDO = orderItemMapper.selectById(orderItemId);
        if (Objects.isNull(orderItemDO)){
            throw exception(ORDER_ITEM_NOT_EXISTS);
        }
        orderItemDO.setOrderItemType(orderItemType);
        orderItemMapper.updateById(orderItemDO);
    }

    @Override
    public void deleteOrderItem(Long id) {
        // 校验存在
        this.validateOrderItemExists(id);
        // 删除
        orderItemMapper.deleteById(id);
    }

    private void validateOrderItemExists(Long id) {
        if (orderItemMapper.selectById(id) == null) {
            throw exception(ORDER_ITEM_NOT_EXISTS);
        }
    }

    @Override
    public OrderItemDO getOrderItem(Long id) {
        return orderItemMapper.selectById(id);
    }

    @Override
    public List<OrderItemSpecialBackVO> specialApplyOrderItem(String orderNo) {
        return orderItemMapper.specialApplyOrderItem(orderNo);
    }

    @Override
    public List<OrderItemDO> getOrderItemList(Collection<Long> ids) {
        return orderItemMapper.selectBatchIds(ids);
    }

    @Override
    public PageResult<OrderItemDO> getOrderItemPage(OrderItemQueryVO query, PageVO page) {
        return orderItemMapper.selectPage(page, query);
    }

    @Override
    public List<OrderItemDO> getOrderItemList(OrderItemQueryVO query) {
        return orderItemMapper.selectList(query);
    }

    @Override
    public List<OrderItemDO> getOrderItemsByOrderId(List<Long> orderIdList) {
        return orderItemMapper.selectList(new LambdaQueryWrapper<OrderItemDO>()
                .in(OrderItemDO::getOrderId, orderIdList)
        );
    }

    @Override
    public List<OrderItemBackVO> getOrderItemBackByOrderId(List<Long> orderIdList) {
        if(CollectionUtil.isEmpty(orderIdList)) return new ArrayList<>();
        return orderItemMapper.orderItemList(I18nMessage.getLang(), orderIdList);
    }

    @Override
    public void updateOrderItemWarehouseInInfoToNull(Long orderId, Long orderItemId) {
        orderItemMapper.updateOrderItemWarehouseInInfoToNull(orderId, orderItemId);
    }

    @Override
    public void updateOrderItemWarehouseInInfoLocation(Long orderId, Set<Long> orderItemIdSet) {
        if (CollectionUtil.isNotEmpty(orderItemIdSet)) {

            List<OrderLocationBackVO> orderLocationBackVOList = null;
            List<OrderLocationMergeVO> orderLocationMergeVOSet = null;

            List<OrderLocationDO> orderLocationListByOrderId = orderLocationMapper.selectList(new LambdaQueryWrapperX<OrderLocationDO>().eq(OrderLocationDO::getOrderId, orderId));

            Map<Long, WarehouseAreaDO> wareMap = warehouseAreaMapper.selectList().stream().collect(Collectors.toMap(WarehouseAreaDO::getId, v -> v));
            Map<Long, WarehouseAreaPositionDO> positionMap = warehouseAreaPositionMapper.selectList().stream().collect(Collectors.toMap(WarehouseAreaPositionDO::getId, v -> v));

            for (Long orderItemId : orderItemIdSet) {
                orderLocationBackVOList = orderLocationListByOrderId.stream()
                        .filter(t -> t.getOrderItemId().equals(orderItemId))
                        .map(OrderLocationConvert.INSTANCE::convert).collect(Collectors.toList());

                //合并 并设置名称
                if (CollectionUtil.isNotEmpty(orderLocationBackVOList)) {
                    orderLocationMergeVOSet = new ArrayList<>();
                    List<OrderLocationMergeVO> mergeList = orderLocationBackVOList.stream().map(orderLocationBackVO ->
                            new OrderLocationMergeVO(orderLocationBackVO.getWareId(), orderLocationBackVO.getAreaId(), orderLocationBackVO.getLocationId())).collect(Collectors.toList());

                    for (OrderLocationMergeVO orderLocation : mergeList) {
                        //过滤
                        if (orderLocationMergeVOSet.stream().noneMatch(t -> t.equals(orderLocation))) {

                            this.setLocationName(orderLocation, wareMap, positionMap);

                            orderLocationMergeVOSet.add(orderLocation);
                        }
                    }
                }

                OrderItemDO orderItemDO = this.getById(orderItemId);
                if (orderItemDO != null) {
                    WarehouseInInfoVO warehouseInInfoVO = orderItemDO.getWarehouseInInfoVO();
                    if (warehouseInInfoVO == null) {
                        warehouseInInfoVO = new WarehouseInInfoVO();
                        orderItemDO.setWarehouseInInfoVO(warehouseInInfoVO);
                    }
                    //设置合并后的储位
                    warehouseInInfoVO.setOrderLocationMergeVOSet(orderLocationMergeVOSet);

                    //设置每一个入仓储位
                    warehouseInInfoVO.setOrderLocationBackVOList(orderLocationBackVOList);

                    orderItemDO.setWarehouseInInfoVO(warehouseInInfoVO);

                    this.updateById(orderItemDO);
                }
            }
        }
    }

    private void setLocationName(OrderLocationMergeVO orderLocation, Map<Long, WarehouseAreaDO> wareMap, Map<Long, WarehouseAreaPositionDO> positionMap) {
        String wareName = "";
        if (orderLocation.getWareId() != null) {
            WarehouseAreaDO wareDO = wareMap.get(orderLocation.getWareId());
            if (wareDO != null) {
                wareName = wareDO.getName();
            }
        }
        orderLocation.setWareName(wareName);

        String areaName = "";
        if (orderLocation.getAreaId() != null) {
            WarehouseAreaDO areaDO = wareMap.get(orderLocation.getAreaId());
            if (areaDO != null) {
                areaName = areaDO.getName();
            }
        }
        orderLocation.setAreaName(areaName);

        String positionName = "";
        if (orderLocation.getLocationId() != null) {
            WarehouseAreaPositionDO positionDO = positionMap.get(orderLocation.getLocationId());
            if (positionDO != null) {
                positionName = positionDO.getCode();
            }
        }
        orderLocation.setLocationName(positionName);
    }

    @Override
    public List<OrderItemDO> getOrderItemListByOrderIdList(List<Long> orderIdList) {
        return orderItemMapper.selectList(new LambdaQueryWrapperX<OrderItemDO>()
            .in(OrderItemDO::getOrderId, orderIdList)
        );
    }
}
