package com.xunhong.erp.turbo.biz.infrastructure.gateway;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.update.LambdaUpdateWrapper;
import com.baomidou.mybatisplus.core.metadata.IPage;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.xunhong.erp.turbo.api.biz.dto.cmd.OrderShipCreateCmd;
import com.xunhong.erp.turbo.api.biz.dto.cmd.OrderShipDestroyCmd;
import com.xunhong.erp.turbo.api.biz.dto.cmd.OrderShipGenerateDocumentCmd;
import com.xunhong.erp.turbo.api.biz.dto.cmd.OrderShipUpdateCmd;
import com.xunhong.erp.turbo.api.biz.dto.common.OrderShipItem;
import com.xunhong.erp.turbo.api.biz.dto.qry.OrderShipListQry;
import com.xunhong.erp.turbo.api.biz.dto.qry.OrderShipPageQry;
import com.xunhong.erp.turbo.api.biz.dto.qry.OrderShipShowQry;
import com.xunhong.erp.turbo.biz.domain.entity.OrderShip;
import com.xunhong.erp.turbo.biz.domain.gateway.OrderShipGateway;
import com.xunhong.erp.turbo.biz.infrastructure.convert.OrderShipConvert;
import com.xunhong.erp.turbo.biz.infrastructure.entity.OrderCostDO;
import com.xunhong.erp.turbo.biz.infrastructure.entity.OrderShipDO;
import com.xunhong.erp.turbo.biz.infrastructure.entity.OrderShipItemDO;
import com.xunhong.erp.turbo.biz.infrastructure.entity.OrderVehicleDO;
import com.xunhong.erp.turbo.biz.infrastructure.mapper.*;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Repository;

import java.util.List;
import java.util.Map;
import java.util.Objects;
import java.util.function.Function;
import java.util.stream.Collectors;

/**
 * @author shenyifei
 */
@Repository
@RequiredArgsConstructor
public class OrderShipGatewayImpl implements OrderShipGateway {
	private final OrderShipMapper orderShipMapper;
	private final OrderShipConvert orderShipConvert;

	private final OrderShipItemMapper orderShipItemMapper;

	private final OrderCostMapper orderCostMapper;
	private final PurchaseOrderMapper purchaseOrderMapper;

	private final OrderVehicleMapper orderVehicleMapper;

	@Override
	public OrderShip save(OrderShipCreateCmd orderShipCreateCmd) {
		OrderShipDO orderShipDO = orderShipConvert.toOrderShipDO(orderShipCreateCmd);
		orderShipMapper.insert(orderShipDO);

		return orderShipConvert.toOrderShip(orderShipDO);
	}

	@Override
	public IPage<OrderShip> page(OrderShipPageQry orderShipPageQry) {
		LambdaQueryWrapper<OrderShipDO> queryWrapper = Wrappers.lambdaQuery(OrderShipDO.class);
		queryWrapper.like(StrUtil.isNotBlank(orderShipPageQry.getOrderSn()), OrderShipDO::getOrderSn, orderShipPageQry.getOrderSn());
		queryWrapper.eq(Objects.nonNull(orderShipPageQry.getState()), OrderShipDO::getState, orderShipPageQry.getState());
		queryWrapper.eq(Objects.nonNull(orderShipPageQry.getCreatedBy()), OrderShipDO::getCreatedBy, orderShipPageQry.getCreatedBy());

		queryWrapper.orderByDesc(OrderShipDO::getCreatedAt);

		IPage<OrderShipDO> page = new Page<>(orderShipPageQry.getPageIndex(), orderShipPageQry.getPageSize());
		page = orderShipMapper.selectPage(page, queryWrapper);

		List<Long> orderIdList = page.getRecords().stream().map(OrderShipDO::getOrderId).toList();
		if (CollUtil.isNotEmpty(orderIdList)) {
			LambdaQueryWrapper<OrderVehicleDO> queryWrapper1 = Wrappers.lambdaQuery(OrderVehicleDO.class);
			queryWrapper1.in(OrderVehicleDO::getOrderId, orderIdList);
			List<OrderVehicleDO> orderVehicleDOList = orderVehicleMapper.selectList(queryWrapper1);
			Map<Long, OrderVehicleDO> orderVehicleDOMap = orderVehicleDOList.stream().collect(Collectors.toMap(OrderVehicleDO::getOrderId, Function.identity()));
			page.getRecords().forEach(orderShipDO -> {
				orderShipDO.setOrderVehicleDO(orderVehicleDOMap.get(orderShipDO.getOrderId()));
			});
		}

		return page.convert(orderShipConvert::toOrderShip);
	}

	@Override
	public List<OrderShip> list(OrderShipListQry orderShipListQry) {
		LambdaQueryWrapper<OrderShipDO> queryWrapper = Wrappers.lambdaQuery(OrderShipDO.class);
		List<OrderShipDO> orderShipDOList = orderShipMapper.selectList(queryWrapper);
		return orderShipDOList.stream().map(orderShipConvert::toOrderShip).toList();
	}

	@Override
	public OrderShip update(OrderShipUpdateCmd orderShipUpdateCmd) {
		LambdaQueryWrapper<OrderShipDO> queryWrapper = Wrappers.lambdaQuery(OrderShipDO.class);
		queryWrapper.eq(OrderShipDO::getOrderShipId, orderShipUpdateCmd.getOrderShipId());
		queryWrapper.last("limit 1");

		OrderShipDO orderShipDO = orderShipMapper.selectOne(queryWrapper);

		orderShipConvert.toOrderShipDO(orderShipDO, orderShipUpdateCmd);
		orderShipMapper.updateById(orderShipDO);

		return orderShipConvert.toOrderShip(orderShipDO);
	}

	@Override
	public OrderShip show(OrderShipShowQry orderShipShowQry) {
		LambdaQueryWrapper<OrderShipDO> queryWrapper = Wrappers.lambdaQuery(OrderShipDO.class);
		queryWrapper.eq(Objects.nonNull(orderShipShowQry.getOrderShipId()), OrderShipDO::getOrderShipId, orderShipShowQry.getOrderShipId());
		queryWrapper.eq(Objects.nonNull(orderShipShowQry.getPurchaseOrderId()), OrderShipDO::getOrderId, orderShipShowQry.getPurchaseOrderId());

		queryWrapper.last("limit 1");

		OrderShipDO orderShipDO = orderShipMapper.selectOne(queryWrapper);

		if (Objects.nonNull(orderShipDO)) {
			orderShipDO.setOrderShipItemDOList(orderShipItemMapper.selectList(Wrappers.lambdaQuery(OrderShipItemDO.class).eq(OrderShipItemDO::getOrderShipId, orderShipDO.getOrderShipId())));
			orderShipDO.setOrderCostDOList(orderCostMapper.selectList(Wrappers.lambdaQuery(OrderCostDO.class).eq(OrderCostDO::getOrderId, orderShipDO.getOrderId())));
		}

		return orderShipConvert.toOrderShip(orderShipDO);
	}

	@Override
	public void destroy(OrderShipDestroyCmd orderShipDestroyCmd) {
		LambdaQueryWrapper<OrderShipDO> queryWrapper = Wrappers.lambdaQuery(OrderShipDO.class);
		queryWrapper.eq(OrderShipDO::getOrderShipId, orderShipDestroyCmd.getOrderShipId());
		queryWrapper.last("limit 1");

		OrderShipDO orderShipDO = orderShipMapper.selectOne(queryWrapper);
		orderShipDO.deleteById();
	}

	@Override
	public void generateDocument(OrderShipGenerateDocumentCmd orderShipGenerateDocumentCmd) {
		LambdaQueryWrapper<OrderShipDO> queryWrapper = Wrappers.lambdaQuery(OrderShipDO.class);
		queryWrapper.eq(OrderShipDO::getOrderShipId, orderShipGenerateDocumentCmd.getOrderShipId());
		queryWrapper.select(OrderShipDO::getOrderShipId, OrderShipDO::getOrderId);
		queryWrapper.last("limit 1");

		OrderShipDO orderShipDO = orderShipMapper.selectOne(queryWrapper);

		// 更新订单明细
		for (OrderShipItem orderShipItem : orderShipGenerateDocumentCmd.getOrderShipItemList()) {
			LambdaUpdateWrapper<OrderShipItemDO> updateWrapper = Wrappers.lambdaUpdate(OrderShipItemDO.class);
			updateWrapper.eq(OrderShipItemDO::getOrderShipId, orderShipDO.getOrderShipId());
			updateWrapper.set(OrderShipItemDO::getWatermelonGrade, orderShipItem.getWatermelonGrade());
			orderShipItemMapper.update(null, updateWrapper);
		}

		orderShipConvert.toOrderShipDO(orderShipDO, orderShipGenerateDocumentCmd);
		orderShipMapper.updateById(orderShipDO);
	}
}

