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

import cn.hutool.core.collection.CollUtil;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
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.DealerWarehouseCreateCmd;
import com.xunhong.erp.turbo.api.biz.dto.cmd.DealerWarehouseDestroyCmd;
import com.xunhong.erp.turbo.api.biz.dto.cmd.DealerWarehouseUpdateCmd;
import com.xunhong.erp.turbo.api.biz.dto.qry.DealerWarehouseListQry;
import com.xunhong.erp.turbo.api.biz.dto.qry.DealerWarehousePageQry;
import com.xunhong.erp.turbo.api.biz.dto.qry.DealerWarehouseShowQry;
import com.xunhong.erp.turbo.biz.domain.entity.DealerWarehouse;
import com.xunhong.erp.turbo.biz.domain.gateway.DealerWarehouseGateway;
import com.xunhong.erp.turbo.biz.infrastructure.convert.DealerWarehouseConvert;
import com.xunhong.erp.turbo.biz.infrastructure.entity.DealerDO;
import com.xunhong.erp.turbo.biz.infrastructure.entity.DealerPaymentAccountDO;
import com.xunhong.erp.turbo.biz.infrastructure.entity.DealerWarehouseDO;
import com.xunhong.erp.turbo.biz.infrastructure.mapper.DealerMapper;
import com.xunhong.erp.turbo.biz.infrastructure.mapper.DealerPaymentAccountMapper;
import com.xunhong.erp.turbo.biz.infrastructure.mapper.DealerWarehouseMapper;
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 DealerWarehouseGatewayImpl implements DealerWarehouseGateway {
	private final DealerWarehouseMapper dealerWarehouseMapper;
	private final DealerMapper dealerMapper;
	private final DealerPaymentAccountMapper dealerPaymentAccountMapper;
	private final DealerWarehouseConvert dealerWarehouseConvert;

	@Override
	public DealerWarehouse save(DealerWarehouseCreateCmd dealerWarehouseCreateCmd) {
		DealerWarehouseDO dealerWarehouseDO = dealerWarehouseConvert.toDealerWarehouseDO(dealerWarehouseCreateCmd);
		dealerWarehouseMapper.insert(dealerWarehouseDO);

		return dealerWarehouseConvert.toDealerWarehouse(dealerWarehouseDO);
	}

	@Override
	public IPage<DealerWarehouse> page(DealerWarehousePageQry dealerWarehousePageQry) {
		LambdaQueryWrapper<DealerWarehouseDO> queryWrapper = Wrappers.lambdaQuery(DealerWarehouseDO.class);
		queryWrapper.eq(Objects.nonNull(dealerWarehousePageQry.getDealerId()), DealerWarehouseDO::getDealerId, dealerWarehousePageQry.getDealerId());
		queryWrapper.eq(Objects.nonNull(dealerWarehousePageQry.getAccountId()), DealerWarehouseDO::getAccountId, dealerWarehousePageQry.getAccountId());
		queryWrapper.eq(Objects.nonNull(dealerWarehousePageQry.getStatus()), DealerWarehouseDO::getStatus, dealerWarehousePageQry.getStatus());
		queryWrapper.orderByDesc(DealerWarehouseDO::getCreatedAt);

		IPage<DealerWarehouseDO> page = new Page<>(dealerWarehousePageQry.getPageIndex(), dealerWarehousePageQry.getPageSize());
		page = dealerWarehouseMapper.selectPage(page, queryWrapper);

		List<Long> dealerIdList = page.getRecords().stream().map(DealerWarehouseDO::getDealerId).toList();
		if (CollUtil.isNotEmpty(dealerIdList)) {
			LambdaQueryWrapper<DealerDO> queryWrapper1 = Wrappers.lambdaQuery(DealerDO.class);
			queryWrapper1.in(DealerDO::getDealerId, dealerIdList);
			List<DealerDO> dealerDOList = dealerMapper.selectList(queryWrapper1);
			Map<Long, DealerDO> dealerDOMap = dealerDOList.stream().collect(Collectors.toMap(DealerDO::getDealerId, Function.identity()));
			page.getRecords().forEach(dealerWarehouseDO -> dealerWarehouseDO.setDealerDO(dealerDOMap.get(dealerWarehouseDO.getDealerId())));
		}

		List<Long> accountIdList = page.getRecords().stream().map(DealerWarehouseDO::getAccountId).toList();
		if (CollUtil.isNotEmpty(accountIdList)) {
			LambdaQueryWrapper<DealerPaymentAccountDO> queryWrapper2 = Wrappers.lambdaQuery(DealerPaymentAccountDO.class);
			queryWrapper2.in(DealerPaymentAccountDO::getAccountId, accountIdList);
			List<DealerPaymentAccountDO> dealerPaymentAccountDOList = dealerPaymentAccountMapper.selectList(queryWrapper2);
			Map<Long, DealerPaymentAccountDO> dealerPaymentAccountDOMap = dealerPaymentAccountDOList.stream().collect(Collectors.toMap(DealerPaymentAccountDO::getAccountId, Function.identity()));
			page.getRecords().forEach(dealerWarehouseDO -> dealerWarehouseDO.setDealerPaymentAccountDO(dealerPaymentAccountDOMap.get(dealerWarehouseDO.getAccountId())));
		}

		return page.convert(dealerWarehouseConvert::toDealerWarehouse);
	}

	@Override
	public List<DealerWarehouse> list(DealerWarehouseListQry dealerWarehouseListQry) {
		LambdaQueryWrapper<DealerWarehouseDO> queryWrapper = Wrappers.lambdaQuery(DealerWarehouseDO.class);
		queryWrapper.eq(Objects.nonNull(dealerWarehouseListQry.getDealerId()), DealerWarehouseDO::getDealerId, dealerWarehouseListQry.getDealerId());
		queryWrapper.eq(Objects.nonNull(dealerWarehouseListQry.getAccountId()), DealerWarehouseDO::getAccountId, dealerWarehouseListQry.getAccountId());
		queryWrapper.eq(Objects.nonNull(dealerWarehouseListQry.getStatus()), DealerWarehouseDO::getStatus, dealerWarehouseListQry.getStatus());
		queryWrapper.orderByDesc(DealerWarehouseDO::getCreatedAt);
		List<DealerWarehouseDO> dealerWarehouseDOList = dealerWarehouseMapper.selectList(queryWrapper);
		return dealerWarehouseDOList.stream().map(dealerWarehouseConvert::toDealerWarehouse).toList();
	}

	@Override
	public DealerWarehouse update(DealerWarehouseUpdateCmd dealerWarehouseUpdateCmd) {
		LambdaQueryWrapper<DealerWarehouseDO> queryWrapper = Wrappers.lambdaQuery(DealerWarehouseDO.class);
		queryWrapper.eq(DealerWarehouseDO::getWarehouseId, dealerWarehouseUpdateCmd.getWarehouseId());
		queryWrapper.last("limit 1");

		DealerWarehouseDO dealerWarehouseDO = dealerWarehouseMapper.selectOne(queryWrapper);

		dealerWarehouseConvert.toDealerWarehouseDO(dealerWarehouseDO, dealerWarehouseUpdateCmd);
		dealerWarehouseMapper.updateById(dealerWarehouseDO);

		return dealerWarehouseConvert.toDealerWarehouse(dealerWarehouseDO);
	}

	@Override
	public DealerWarehouse show(DealerWarehouseShowQry dealerWarehouseShowQry) {
		LambdaQueryWrapper<DealerWarehouseDO> queryWrapper = Wrappers.lambdaQuery(DealerWarehouseDO.class);
		queryWrapper.eq(DealerWarehouseDO::getWarehouseId, dealerWarehouseShowQry.getWarehouseId());
		queryWrapper.last("limit 1");

		DealerWarehouseDO dealerWarehouseDO = dealerWarehouseMapper.selectOne(queryWrapper);
		if (Objects.nonNull(dealerWarehouseDO)) {
			dealerWarehouseDO.setDealerDO(dealerMapper.selectById(dealerWarehouseDO.getDealerId()));
			dealerWarehouseDO.setDealerPaymentAccountDO(dealerPaymentAccountMapper.selectById(dealerWarehouseDO.getAccountId()));
		}

		return dealerWarehouseConvert.toDealerWarehouse(dealerWarehouseDO);
	}

	@Override
	public void destroy(DealerWarehouseDestroyCmd dealerWarehouseDestroyCmd) {
		LambdaQueryWrapper<DealerWarehouseDO> queryWrapper = Wrappers.lambdaQuery(DealerWarehouseDO.class);
		queryWrapper.eq(DealerWarehouseDO::getWarehouseId, dealerWarehouseDestroyCmd.getWarehouseId());
		queryWrapper.last("limit 1");

		DealerWarehouseDO dealerWarehouseDO = dealerWarehouseMapper.selectOne(queryWrapper);
		dealerWarehouseDO.deleteById();
	}
}

