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.SupplierCreateCmd;
import com.xunhong.erp.turbo.api.biz.dto.cmd.SupplierDestroyCmd;
import com.xunhong.erp.turbo.api.biz.dto.cmd.SupplierUpdateCmd;
import com.xunhong.erp.turbo.api.biz.dto.qry.SupplierCheckQry;
import com.xunhong.erp.turbo.api.biz.dto.qry.SupplierListQry;
import com.xunhong.erp.turbo.api.biz.dto.qry.SupplierPageQry;
import com.xunhong.erp.turbo.api.biz.dto.qry.SupplierShowQry;
import com.xunhong.erp.turbo.biz.domain.entity.Supplier;
import com.xunhong.erp.turbo.biz.domain.gateway.SupplierGateway;
import com.xunhong.erp.turbo.biz.infrastructure.convert.SupplierConvert;
import com.xunhong.erp.turbo.biz.infrastructure.entity.DealerDO;
import com.xunhong.erp.turbo.biz.infrastructure.entity.SupplierDO;
import com.xunhong.erp.turbo.biz.infrastructure.mapper.DealerMapper;
import com.xunhong.erp.turbo.biz.infrastructure.mapper.SupplierMapper;
import com.xunhong.erp.turbo.datasource.util.AesUtil;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Repository;

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

/**
 * @author shenyifei
 */
@Repository
@RequiredArgsConstructor
public class SupplierGatewayImpl implements SupplierGateway {
	private final SupplierMapper supplierMapper;
	private final SupplierConvert supplierConvert;

	private final DealerMapper dealerMapper;

	@Override
	public Supplier save(SupplierCreateCmd supplierCreateCmd) {
		SupplierDO supplierDO = supplierConvert.toSupplierDO(supplierCreateCmd);
		supplierMapper.insert(supplierDO);

		return supplierConvert.toSupplier(supplierDO);
	}

	@Override
	public IPage<Supplier> page(SupplierPageQry supplierPageQry) {
		LambdaQueryWrapper<SupplierDO> queryWrapper = Wrappers.lambdaQuery(SupplierDO.class);
		queryWrapper.like(Objects.nonNull(supplierPageQry.getName()), SupplierDO::getName, supplierPageQry.getName());
		queryWrapper.like(Objects.nonNull(supplierPageQry.getIdCard()), SupplierDO::getIdCard, supplierPageQry.getIdCard());
		queryWrapper.eq(Objects.nonNull(supplierPageQry.getDealerId()), SupplierDO::getDealerId, supplierPageQry.getDealerId());
		queryWrapper.like(Objects.nonNull(supplierPageQry.getPhone()), SupplierDO::getPhone, supplierPageQry.getPhone());
		queryWrapper.like(Objects.nonNull(supplierPageQry.getBankCard()), SupplierDO::getBankCard, supplierPageQry.getBankCard());
		queryWrapper.eq(Objects.nonNull(supplierPageQry.getStatus()), SupplierDO::getStatus, supplierPageQry.getStatus());
		queryWrapper.eq(Objects.nonNull(supplierPageQry.getType()), SupplierDO::getType, supplierPageQry.getType());
		queryWrapper.orderByDesc(SupplierDO::getCreatedAt);

		IPage<SupplierDO> page = new Page<>(supplierPageQry.getPageIndex(), supplierPageQry.getPageSize());
		page = supplierMapper.selectPage(page, queryWrapper);

		Set<Long> dealerIdList = page.getRecords().stream().map(SupplierDO::getDealerId).collect(Collectors.toSet());
		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(supplierDO -> supplierDO.setDealerDO(dealerDOMap.get(supplierDO.getDealerId())));
		}

		return page.convert(supplierConvert::toSupplier);
	}

	@Override
	public List<Supplier> list(SupplierListQry supplierListQry) {
		LambdaQueryWrapper<SupplierDO> queryWrapper = Wrappers.lambdaQuery(SupplierDO.class);
		queryWrapper.eq(Objects.nonNull(supplierListQry.getSupplierId()), SupplierDO::getSupplierId, supplierListQry.getSupplierId());
		queryWrapper.eq(Objects.nonNull(supplierListQry.getDealerId()), SupplierDO::getDealerId, supplierListQry.getDealerId());
		queryWrapper.like(Objects.nonNull(supplierListQry.getName()), SupplierDO::getName, supplierListQry.getName());
		queryWrapper.eq(Objects.nonNull(supplierListQry.getStatus()), SupplierDO::getStatus, supplierListQry.getStatus());
		queryWrapper.eq(Objects.nonNull(supplierListQry.getType()), SupplierDO::getType, supplierListQry.getType());

		queryWrapper.orderByDesc(SupplierDO::getCreatedAt);
		List<SupplierDO> supplierDOList = supplierMapper.selectList(queryWrapper);
		return supplierDOList.stream().map(supplierConvert::toSupplier).toList();
	}

	@Override
	public Supplier update(SupplierUpdateCmd supplierUpdateCmd) {
		LambdaQueryWrapper<SupplierDO> queryWrapper = Wrappers.lambdaQuery(SupplierDO.class);
		queryWrapper.eq(SupplierDO::getSupplierId, supplierUpdateCmd.getSupplierId());
		queryWrapper.last("limit 1");

		SupplierDO supplierDO = supplierMapper.selectOne(queryWrapper);

		supplierConvert.toSupplierDO(supplierDO, supplierUpdateCmd);
		supplierMapper.updateById(supplierDO);

		return supplierConvert.toSupplier(supplierDO);
	}

	@Override
	public Supplier show(SupplierShowQry supplierShowQry) {
		LambdaQueryWrapper<SupplierDO> queryWrapper = Wrappers.lambdaQuery(SupplierDO.class);
		queryWrapper.eq(SupplierDO::getSupplierId, supplierShowQry.getSupplierId());
		queryWrapper.last("limit 1");

		SupplierDO supplierDO = supplierMapper.selectOne(queryWrapper);
		if (Objects.nonNull(supplierDO)) {
			supplierDO.setDealerDO(dealerMapper.selectById(supplierDO.getDealerId()));
		}
		return supplierConvert.toSupplier(supplierDO);
	}

	@Override
	public void destroy(SupplierDestroyCmd supplierDestroyCmd) {
		LambdaQueryWrapper<SupplierDO> queryWrapper = Wrappers.lambdaQuery(SupplierDO.class);
		queryWrapper.eq(SupplierDO::getSupplierId, supplierDestroyCmd.getSupplierId());
		queryWrapper.last("limit 1");

		SupplierDO supplierDO = supplierMapper.selectOne(queryWrapper);
		supplierDO.deleteById();
	}

	@Override
	public Supplier check(SupplierCheckQry supplierCheckQry) {
		LambdaQueryWrapper<SupplierDO> queryWrapper = Wrappers.lambdaQuery(SupplierDO.class);
		queryWrapper.eq(Objects.nonNull(supplierCheckQry.getPhone()), SupplierDO::getPhone, AesUtil.encrypt(supplierCheckQry.getPhone()));
		queryWrapper.eq(Objects.nonNull(supplierCheckQry.getIdCard()), SupplierDO::getIdCard, AesUtil.encrypt(supplierCheckQry.getIdCard()));
		queryWrapper.eq(Objects.nonNull(supplierCheckQry.getName()), SupplierDO::getName, supplierCheckQry.getName());
		queryWrapper.ne(Objects.nonNull(supplierCheckQry.getSupplierId()), SupplierDO::getSupplierId, supplierCheckQry.getSupplierId());

		queryWrapper.last("limit 1");
		SupplierDO userDO = supplierMapper.selectOne(queryWrapper);
		if (Objects.isNull(userDO)) {
			return null;
		}

		return supplierConvert.toSupplier(userDO);
	}
}

