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

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.infra.dto.cmd.AgreementCreateCmd;
import com.xunhong.erp.turbo.api.infra.dto.cmd.AgreementDestroyCmd;
import com.xunhong.erp.turbo.api.infra.dto.cmd.AgreementUpdateCmd;
import com.xunhong.erp.turbo.api.infra.dto.qry.AgreementListQry;
import com.xunhong.erp.turbo.api.infra.dto.qry.AgreementPageQry;
import com.xunhong.erp.turbo.api.infra.dto.qry.AgreementShowQry;
import com.xunhong.erp.turbo.infra.domain.entity.Agreement;
import com.xunhong.erp.turbo.infra.domain.gateway.AgreementGateway;
import com.xunhong.erp.turbo.infra.infrastructure.convert.AgreementConvert;
import com.xunhong.erp.turbo.infra.infrastructure.entity.AgreementDO;
import com.xunhong.erp.turbo.infra.infrastructure.mapper.AgreementMapper;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Repository;

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

/**
 * @author shenyifei
 */
@Repository
@RequiredArgsConstructor
public class AgreementGatewayImpl implements AgreementGateway {
	private final AgreementMapper agreementMapper;
	private final AgreementConvert agreementConvert;

	@Override
	public Agreement save(AgreementCreateCmd agreementCreateCmd) {
		AgreementDO agreementDO = agreementConvert.toAgreementDO(agreementCreateCmd);
		agreementMapper.insert(agreementDO);

		return agreementConvert.toAgreement(agreementDO);
	}

	@Override
	public IPage<Agreement> page(AgreementPageQry agreementPageQry) {
		LambdaQueryWrapper<AgreementDO> queryWrapper = Wrappers.lambdaQuery(AgreementDO.class);
		if (Objects.nonNull(agreementPageQry.getScene())) {
			queryWrapper.apply("JSON_CONTAINS(scene, JSON_ARRAY({0})) = 1", agreementPageQry.getScene());
		}

		queryWrapper.orderByDesc(AgreementDO::getCreatedAt);

		IPage<AgreementDO> page = new Page<>(agreementPageQry.getPageIndex(), agreementPageQry.getPageSize());
		page = agreementMapper.selectPage(page, queryWrapper);

		return page.convert(agreementConvert::toAgreement);
	}

	@Override
	public List<Agreement> list(AgreementListQry agreementListQry) {
		LambdaQueryWrapper<AgreementDO> queryWrapper = Wrappers.lambdaQuery(AgreementDO.class);
		queryWrapper.eq(Objects.nonNull(agreementListQry.getAgreementId()), AgreementDO::getAgreementId, agreementListQry.getAgreementId());
		if (Objects.nonNull(agreementListQry.getScene())) {
			queryWrapper.apply("JSON_CONTAINS(scene, JSON_ARRAY({0})) = 1", agreementListQry.getScene());
		}

		queryWrapper.select(AgreementDO::getAgreementId, AgreementDO::getTitle);
		List<AgreementDO> agreementDOList = agreementMapper.selectList(queryWrapper);
		return agreementDOList.stream().map(agreementConvert::toAgreement).toList();
	}

	@Override
	public Agreement update(AgreementUpdateCmd agreementUpdateCmd) {
		LambdaQueryWrapper<AgreementDO> queryWrapper = Wrappers.lambdaQuery(AgreementDO.class);
		queryWrapper.eq(AgreementDO::getAgreementId, agreementUpdateCmd.getAgreementId());
		queryWrapper.last("limit 1");

		AgreementDO agreementDO = agreementMapper.selectOne(queryWrapper);

		agreementConvert.toAgreementDO(agreementDO, agreementUpdateCmd);
		agreementMapper.updateById(agreementDO);

		return agreementConvert.toAgreement(agreementDO);
	}

	@Override
	public Agreement show(AgreementShowQry agreementShowQry) {
		LambdaQueryWrapper<AgreementDO> queryWrapper = Wrappers.lambdaQuery(AgreementDO.class);
		queryWrapper.eq(AgreementDO::getAgreementId, agreementShowQry.getAgreementId());
		queryWrapper.last("limit 1");

		AgreementDO agreementDO = agreementMapper.selectOne(queryWrapper);
		return agreementConvert.toAgreement(agreementDO);
	}

	@Override
	public void destroy(AgreementDestroyCmd agreementDestroyCmd) {
		LambdaQueryWrapper<AgreementDO> queryWrapper = Wrappers.lambdaQuery(AgreementDO.class);
		queryWrapper.eq(AgreementDO::getAgreementId, agreementDestroyCmd.getAgreementId());
		queryWrapper.last("limit 1");

		AgreementDO agreementDO = agreementMapper.selectOne(queryWrapper);
		agreementDO.deleteById();
	}
}

