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

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.ShipOrderCreateCmd;
import com.xunhong.erp.turbo.api.biz.dto.cmd.ShipOrderDestroyCmd;
import com.xunhong.erp.turbo.api.biz.dto.cmd.ShipOrderGenerateDocumentCmd;
import com.xunhong.erp.turbo.api.biz.dto.cmd.ShipOrderUpdateCmd;
import com.xunhong.erp.turbo.api.biz.dto.common.ShipOrderItem;
import com.xunhong.erp.turbo.api.biz.dto.qry.ShipOrderListQry;
import com.xunhong.erp.turbo.api.biz.dto.qry.ShipOrderPageQry;
import com.xunhong.erp.turbo.api.biz.dto.qry.ShipOrderShowQry;
import com.xunhong.erp.turbo.biz.domain.entity.ShipOrder;
import com.xunhong.erp.turbo.biz.domain.gateway.ShipOrderGateway;
import com.xunhong.erp.turbo.biz.infrastructure.convert.ShipOrderConvert;
import com.xunhong.erp.turbo.biz.infrastructure.entity.OrderCostDO;
import com.xunhong.erp.turbo.biz.infrastructure.entity.ShipOrderDO;
import com.xunhong.erp.turbo.biz.infrastructure.entity.ShipOrderItemDO;
import com.xunhong.erp.turbo.biz.infrastructure.entity.ShipOrderPackageDO;
import com.xunhong.erp.turbo.biz.infrastructure.mapper.OrderCostMapper;
import com.xunhong.erp.turbo.biz.infrastructure.mapper.ShipOrderItemMapper;
import com.xunhong.erp.turbo.biz.infrastructure.mapper.ShipOrderMapper;
import com.xunhong.erp.turbo.biz.infrastructure.mapper.ShipOrderPackageMapper;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Repository;

import java.util.List;
import java.util.Objects;

/**
 * @author shenyifei
 */
@Repository
@RequiredArgsConstructor
public class ShipOrderGatewayImpl implements ShipOrderGateway {
	private final ShipOrderMapper shipOrderMapper;
	private final ShipOrderConvert shipOrderConvert;

	private final ShipOrderItemMapper shipOrderItemMapper;
	private final ShipOrderPackageMapper shipOrderPackageMapper;

	private final OrderCostMapper orderCostMapper;

	@Override
	public ShipOrder save(ShipOrderCreateCmd shipOrderCreateCmd) {
		ShipOrderDO shipOrderDO = shipOrderConvert.toShipOrderDO(shipOrderCreateCmd);
		shipOrderMapper.insert(shipOrderDO);

		return shipOrderConvert.toShipOrder(shipOrderDO);
	}

	@Override
	public IPage<ShipOrder> page(ShipOrderPageQry shipOrderPageQry) {
		LambdaQueryWrapper<ShipOrderDO> queryWrapper = Wrappers.lambdaQuery(ShipOrderDO.class);
		queryWrapper.like(StrUtil.isNotBlank(shipOrderPageQry.getOrderSn()), ShipOrderDO::getOrderSn, shipOrderPageQry.getOrderSn());
		queryWrapper.eq(Objects.nonNull(shipOrderPageQry.getState()), ShipOrderDO::getState, shipOrderPageQry.getState());
		queryWrapper.eq(Objects.nonNull(shipOrderPageQry.getCreatedBy()), ShipOrderDO::getCreatedBy, shipOrderPageQry.getCreatedBy());
		queryWrapper.like(StrUtil.isNotBlank(shipOrderPageQry.getVehicleNo()), ShipOrderDO::getVehicleNo, shipOrderPageQry.getVehicleNo());
		queryWrapper.eq(Objects.nonNull(shipOrderPageQry.getDealerId()), ShipOrderDO::getDealerId, shipOrderPageQry.getDealerId());

		queryWrapper.orderByDesc(ShipOrderDO::getCreatedAt);

		IPage<ShipOrderDO> page = new Page<>(shipOrderPageQry.getPageIndex(), shipOrderPageQry.getPageSize());
		page = shipOrderMapper.selectPage(page, queryWrapper);

		return page.convert(shipOrderConvert::toShipOrder);
	}

	@Override
	public List<ShipOrder> list(ShipOrderListQry shipOrderListQry) {
		LambdaQueryWrapper<ShipOrderDO> queryWrapper = Wrappers.lambdaQuery(ShipOrderDO.class);
		List<ShipOrderDO> shipOrderDOList = shipOrderMapper.selectList(queryWrapper);
		return shipOrderDOList.stream().map(shipOrderConvert::toShipOrder).toList();
	}

	@Override
	public ShipOrder update(ShipOrderUpdateCmd shipOrderUpdateCmd) {
		LambdaQueryWrapper<ShipOrderDO> queryWrapper = Wrappers.lambdaQuery(ShipOrderDO.class);
		queryWrapper.eq(ShipOrderDO::getShipOrderId, shipOrderUpdateCmd.getShipOrderId());
		queryWrapper.last("limit 1");

		ShipOrderDO shipOrderDO = shipOrderMapper.selectOne(queryWrapper);

		shipOrderConvert.toShipOrderDO(shipOrderDO, shipOrderUpdateCmd);
		shipOrderMapper.updateById(shipOrderDO);

		return shipOrderConvert.toShipOrder(shipOrderDO);
	}

	@Override
	public ShipOrder show(ShipOrderShowQry shipOrderShowQry) {
		LambdaQueryWrapper<ShipOrderDO> queryWrapper = Wrappers.lambdaQuery(ShipOrderDO.class);
		queryWrapper.eq(Objects.nonNull(shipOrderShowQry.getShipOrderId()), ShipOrderDO::getShipOrderId, shipOrderShowQry.getShipOrderId());
		queryWrapper.eq(Objects.nonNull(shipOrderShowQry.getPurchaseOrderId()), ShipOrderDO::getPurchaseOrderId, shipOrderShowQry.getPurchaseOrderId());

		queryWrapper.last("limit 1");

		ShipOrderDO shipOrderDO = shipOrderMapper.selectOne(queryWrapper);

		if (Objects.nonNull(shipOrderDO)) {
			shipOrderDO.setShipOrderItemDOList(shipOrderItemMapper.selectList(Wrappers.lambdaQuery(ShipOrderItemDO.class).eq(ShipOrderItemDO::getShipOrderId, shipOrderDO.getShipOrderId())));
			shipOrderDO.setShipOrderPackageDOList(shipOrderPackageMapper.selectList(Wrappers.lambdaQuery(ShipOrderPackageDO.class).eq(ShipOrderPackageDO::getShipOrderId, shipOrderDO.getShipOrderId())));
			shipOrderDO.setOrderCostDOList(orderCostMapper.selectList(Wrappers.lambdaQuery(OrderCostDO.class).eq(OrderCostDO::getOrderId, shipOrderDO.getPurchaseOrderId())));
		}

		return shipOrderConvert.toShipOrder(shipOrderDO);
	}

	@Override
	public void destroy(ShipOrderDestroyCmd shipOrderDestroyCmd) {
		LambdaQueryWrapper<ShipOrderDO> queryWrapper = Wrappers.lambdaQuery(ShipOrderDO.class);
		queryWrapper.eq(ShipOrderDO::getShipOrderId, shipOrderDestroyCmd.getShipOrderId());
		queryWrapper.last("limit 1");

		ShipOrderDO shipOrderDO = shipOrderMapper.selectOne(queryWrapper);
		shipOrderDO.deleteById();
	}

	@Override
	public void generateDocument(ShipOrderGenerateDocumentCmd shipOrderGenerateDocumentCmd) {
		LambdaQueryWrapper<ShipOrderDO> queryWrapper = Wrappers.lambdaQuery(ShipOrderDO.class);
		queryWrapper.eq(ShipOrderDO::getShipOrderId, shipOrderGenerateDocumentCmd.getShipOrderId());
		queryWrapper.select(ShipOrderDO::getShipOrderId, ShipOrderDO::getPurchaseOrderId);
		queryWrapper.last("limit 1");

		ShipOrderDO shipOrderDO = shipOrderMapper.selectOne(queryWrapper);

		// 更新订单明细
		for (ShipOrderItem shipOrderItem : shipOrderGenerateDocumentCmd.getShipOrderItemList()) {
			LambdaUpdateWrapper<ShipOrderItemDO> updateWrapper = Wrappers.lambdaUpdate(ShipOrderItemDO.class);
			updateWrapper.eq(ShipOrderItemDO::getShipOrderId, shipOrderDO.getShipOrderId());
			updateWrapper.set(ShipOrderItemDO::getWatermelonGrade, shipOrderItem.getWatermelonGrade());
			shipOrderItemMapper.update(null, updateWrapper);
		}

		shipOrderConvert.toShipOrderDO(shipOrderDO, shipOrderGenerateDocumentCmd);
		shipOrderMapper.updateById(shipOrderDO);
	}
}

