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.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.DealerPaymentAccountCreateCmd;
import com.xunhong.erp.turbo.api.biz.dto.cmd.DealerPaymentAccountDestroyCmd;
import com.xunhong.erp.turbo.api.biz.dto.cmd.DealerPaymentAccountUpdateCmd;
import com.xunhong.erp.turbo.api.biz.dto.qry.DealerPaymentAccountListQry;
import com.xunhong.erp.turbo.api.biz.dto.qry.DealerPaymentAccountPageQry;
import com.xunhong.erp.turbo.api.biz.dto.qry.DealerPaymentAccountShowQry;
import com.xunhong.erp.turbo.biz.domain.entity.DealerPaymentAccount;
import com.xunhong.erp.turbo.biz.domain.gateway.DealerPaymentAccountGateway;
import com.xunhong.erp.turbo.biz.infrastructure.convert.DealerPaymentAccountConvert;
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.mapper.DealerMapper;
import com.xunhong.erp.turbo.biz.infrastructure.mapper.DealerPaymentAccountMapper;
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 DealerPaymentAccountGatewayImpl implements DealerPaymentAccountGateway {
	private final DealerPaymentAccountMapper dealerPaymentAccountMapper;
	private final DealerMapper dealerMapper;
	private final DealerPaymentAccountConvert dealerPaymentAccountConvert;

	@Override
	public DealerPaymentAccount save(DealerPaymentAccountCreateCmd dealerPaymentAccountCreateCmd) {
		DealerPaymentAccountDO dealerPaymentAccountDO = dealerPaymentAccountConvert.toDealerPaymentAccountDO(dealerPaymentAccountCreateCmd);
		dealerPaymentAccountMapper.insert(dealerPaymentAccountDO);

		return dealerPaymentAccountConvert.toDealerPaymentAccount(dealerPaymentAccountDO);
	}

	@Override
	public IPage<DealerPaymentAccount> page(DealerPaymentAccountPageQry dealerPaymentAccountPageQry) {
		LambdaQueryWrapper<DealerPaymentAccountDO> queryWrapper = Wrappers.lambdaQuery(DealerPaymentAccountDO.class);
		queryWrapper.eq(Objects.nonNull(dealerPaymentAccountPageQry.getDealerId()), DealerPaymentAccountDO::getDealerId, dealerPaymentAccountPageQry.getDealerId());
		queryWrapper.orderByDesc(DealerPaymentAccountDO::getCreatedAt);

		IPage<DealerPaymentAccountDO> page = new Page<>(dealerPaymentAccountPageQry.getPageIndex(), dealerPaymentAccountPageQry.getPageSize());
		page = dealerPaymentAccountMapper.selectPage(page, queryWrapper);

		List<Long> dealerIdList = page.getRecords().stream().map(DealerPaymentAccountDO::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(dealerPaymentAccountDO -> dealerPaymentAccountDO.setDealerDO(dealerDOMap.get(dealerPaymentAccountDO.getDealerId())));
		}

		return page.convert(dealerPaymentAccountConvert::toDealerPaymentAccount);
	}

	@Override
	public List<DealerPaymentAccount> list(DealerPaymentAccountListQry dealerPaymentAccountListQry) {
		LambdaQueryWrapper<DealerPaymentAccountDO> queryWrapper = Wrappers.lambdaQuery(DealerPaymentAccountDO.class);
		queryWrapper.eq(Objects.nonNull(dealerPaymentAccountListQry.getDealerId()), DealerPaymentAccountDO::getDealerId, dealerPaymentAccountListQry.getDealerId());
		if (StrUtil.isNotBlank(dealerPaymentAccountListQry.getKeyword())) {
			// 先根据经销商名称查询经销商ID列表
			LambdaQueryWrapper<DealerDO> dealerQueryWrapper = Wrappers.lambdaQuery(DealerDO.class);
			dealerQueryWrapper.like(DealerDO::getFullName, dealerPaymentAccountListQry.getKeyword())
				.or()
				.like(DealerDO::getShortName, dealerPaymentAccountListQry.getKeyword());
			List<DealerDO> dealerDOList = dealerMapper.selectList(dealerQueryWrapper);
			List<Long> dealerIds = dealerDOList.stream().map(DealerDO::getDealerId).toList();

			queryWrapper.and(wrapper -> wrapper
				.like(DealerPaymentAccountDO::getCompanyName, dealerPaymentAccountListQry.getKeyword())
				.or()
				.like(DealerPaymentAccountDO::getBankAccount, dealerPaymentAccountListQry.getKeyword())
				.or(wrapper2 -> {
					if (!dealerIds.isEmpty()) {
						wrapper2.in(DealerPaymentAccountDO::getDealerId, dealerIds);
					} else {
						// 如果没有匹配的经销商ID，则添加一个永远不成立的条件
						wrapper2.eq(DealerPaymentAccountDO::getDealerId, -1L);
					}
				}));
		}
		queryWrapper.orderByDesc(DealerPaymentAccountDO::getDealerId);
		queryWrapper.orderByDesc(DealerPaymentAccountDO::getCreatedAt);
		List<DealerPaymentAccountDO> dealerPaymentAccountDOList = dealerPaymentAccountMapper.selectList(queryWrapper);

		// 查询相关的经销商信息
		Set<Long> dealerIds = dealerPaymentAccountDOList.stream()
			.map(DealerPaymentAccountDO::getDealerId)
			.filter(Objects::nonNull)
			.collect(Collectors.toSet());
		if (!dealerIds.isEmpty()) {
			LambdaQueryWrapper<DealerDO> dealerQueryWrapper = Wrappers.lambdaQuery(DealerDO.class);
			dealerQueryWrapper.in(DealerDO::getDealerId, dealerIds);
			List<DealerDO> dealerDOList = dealerMapper.selectList(dealerQueryWrapper);
			Map<Long, DealerDO> dealerDOMap = dealerDOList.stream().collect(Collectors.toMap(DealerDO::getDealerId, Function.identity()));
			dealerPaymentAccountDOList.forEach(dealerPaymentAccountDO -> dealerPaymentAccountDO.setDealerDO(dealerDOMap.get(dealerPaymentAccountDO.getDealerId())));
		}

		return dealerPaymentAccountDOList.stream().map(dealerPaymentAccountConvert::toDealerPaymentAccount).toList();
	}

	@Override
	public DealerPaymentAccount update(DealerPaymentAccountUpdateCmd dealerPaymentAccountUpdateCmd) {
		LambdaQueryWrapper<DealerPaymentAccountDO> queryWrapper = Wrappers.lambdaQuery(DealerPaymentAccountDO.class);
		queryWrapper.eq(DealerPaymentAccountDO::getAccountId, dealerPaymentAccountUpdateCmd.getAccountId());
		queryWrapper.last("limit 1");

		DealerPaymentAccountDO dealerPaymentAccountDO = dealerPaymentAccountMapper.selectOne(queryWrapper);

		dealerPaymentAccountConvert.toDealerPaymentAccountDO(dealerPaymentAccountDO, dealerPaymentAccountUpdateCmd);
		dealerPaymentAccountMapper.updateById(dealerPaymentAccountDO);

		return dealerPaymentAccountConvert.toDealerPaymentAccount(dealerPaymentAccountDO);
	}

	@Override
	public DealerPaymentAccount show(DealerPaymentAccountShowQry dealerPaymentAccountShowQry) {
		LambdaQueryWrapper<DealerPaymentAccountDO> queryWrapper = Wrappers.lambdaQuery(DealerPaymentAccountDO.class);
		queryWrapper.eq(DealerPaymentAccountDO::getAccountId, dealerPaymentAccountShowQry.getAccountId());
		queryWrapper.last("limit 1");

		DealerPaymentAccountDO dealerPaymentAccountDO = dealerPaymentAccountMapper.selectOne(queryWrapper);

		if (Objects.nonNull(dealerPaymentAccountDO)) {
			dealerPaymentAccountDO.setDealerDO(dealerMapper.selectById(dealerPaymentAccountDO.getDealerId()));
		}

		return dealerPaymentAccountConvert.toDealerPaymentAccount(dealerPaymentAccountDO);
	}

	@Override
	public void destroy(DealerPaymentAccountDestroyCmd dealerPaymentAccountDestroyCmd) {
		LambdaQueryWrapper<DealerPaymentAccountDO> queryWrapper = Wrappers.lambdaQuery(DealerPaymentAccountDO.class);
		queryWrapper.eq(DealerPaymentAccountDO::getAccountId, dealerPaymentAccountDestroyCmd.getAccountId());
		queryWrapper.last("limit 1");

		DealerPaymentAccountDO dealerPaymentAccountDO = dealerPaymentAccountMapper.selectOne(queryWrapper);
		dealerPaymentAccountDO.deleteById();
	}
}

