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

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.alibaba.cola.exception.BizException;
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.CategoryCreateCmd;
import com.xunhong.erp.turbo.api.infra.dto.cmd.CategoryDestroyCmd;
import com.xunhong.erp.turbo.api.infra.dto.cmd.CategoryUpdateCmd;
import com.xunhong.erp.turbo.api.infra.dto.qry.CategoryPageQry;
import com.xunhong.erp.turbo.api.infra.dto.qry.CategoryShowQry;
import com.xunhong.erp.turbo.api.infra.dto.qry.CategoryTreeQry;
import com.xunhong.erp.turbo.infra.domain.entity.Category;
import com.xunhong.erp.turbo.infra.domain.gateway.CategoryGateway;
import com.xunhong.erp.turbo.infra.infrastructure.convert.CategoryConvert;
import com.xunhong.erp.turbo.infra.infrastructure.entity.CategoryDO;
import com.xunhong.erp.turbo.infra.infrastructure.mapper.CategoryMapper;
import lombok.RequiredArgsConstructor;
import org.springframework.stereotype.Repository;

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


/**
 * @author shenyifei
 */
@Repository
@RequiredArgsConstructor
public class CategoryGatewayImpl implements CategoryGateway {
	private final CategoryMapper categoryMapper;
	private final CategoryConvert categoryConvert;


	@Override
	public IPage<Category> page(CategoryPageQry categoryPageQry) {
		LambdaQueryWrapper<CategoryDO> queryWrapper = Wrappers.lambdaQuery(CategoryDO.class);
		queryWrapper.like(StrUtil.isNotEmpty(categoryPageQry.getName()), CategoryDO::getName, categoryPageQry.getName());
		queryWrapper.eq(Objects.nonNull(categoryPageQry.getType()), CategoryDO::getType, categoryPageQry.getType());
		queryWrapper.in(CollUtil.isNotEmpty(categoryPageQry.getTypeList()), CategoryDO::getType, categoryPageQry.getTypeList());

		queryWrapper.orderByDesc(CategoryDO::getSort);
		queryWrapper.orderByDesc(CategoryDO::getCreatedAt);

		Page<CategoryDO> page = new Page<>(categoryPageQry.getPageIndex(), categoryPageQry.getPageSize());
		categoryMapper.selectPage(page, queryWrapper);

		return page.convert(categoryConvert::toCategory);
	}

	@Override
	public List<Category> list(CategoryTreeQry categoryTreeQry) {
		LambdaQueryWrapper<CategoryDO> queryWrapper = Wrappers.lambdaQuery(CategoryDO.class);
		queryWrapper.like(StrUtil.isNotEmpty(categoryTreeQry.getName()), CategoryDO::getName, categoryTreeQry.getName());
		queryWrapper.eq(Objects.nonNull(categoryTreeQry.getType()), CategoryDO::getType, categoryTreeQry.getType());
		queryWrapper.in(CollUtil.isNotEmpty(categoryTreeQry.getTypeList()), CategoryDO::getType, categoryTreeQry.getTypeList());

		queryWrapper.orderByDesc(CategoryDO::getSort);
		queryWrapper.orderByDesc(CategoryDO::getCreatedAt);
		List<CategoryDO> categoryDOList = categoryMapper.selectList(queryWrapper);
		return categoryDOList.stream().map(categoryConvert::toCategory).toList();
	}

	@Override
	public Category update(CategoryUpdateCmd categoryUpdateCmd) {
		LambdaQueryWrapper<CategoryDO> queryWrapper = Wrappers.lambdaQuery(CategoryDO.class);
		queryWrapper.eq(CategoryDO::getCategoryId, categoryUpdateCmd.getCategoryId());
		queryWrapper.eq(CategoryDO::getType, categoryUpdateCmd.getType());
		queryWrapper.select(CategoryDO::getCategoryId);

		queryWrapper.last("limit 1");
		CategoryDO categoryDO = categoryMapper.selectOne(queryWrapper);

		categoryConvert.toCategoryDO(categoryDO, categoryUpdateCmd);
		categoryMapper.updateById(categoryDO);

		return categoryConvert.toCategory(categoryDO);
	}

	@Override
	public Category save(CategoryCreateCmd categoryCreateCmd) {
		CategoryDO categoryDO = categoryConvert.toCategoryDO(categoryCreateCmd);

		categoryMapper.insert(categoryDO);

		return categoryConvert.toCategory(categoryDO);
	}

	@Override
	public Category show(CategoryShowQry categoryShowQry) {
		LambdaQueryWrapper<CategoryDO> queryWrapper = Wrappers.lambdaQuery(CategoryDO.class);
		queryWrapper.eq(CategoryDO::getCategoryId, categoryShowQry.getCategoryId());
		queryWrapper.eq(Objects.nonNull(categoryShowQry.getType()), CategoryDO::getType, categoryShowQry.getType());

		queryWrapper.last("limit 1");
		CategoryDO categoryDO = categoryMapper.selectOne(queryWrapper);
		return categoryConvert.toCategory(categoryDO);
	}

	@Override
	public void destroy(CategoryDestroyCmd categoryDestroyCmd) {
		LambdaQueryWrapper<CategoryDO> queryWrapper = Wrappers.lambdaQuery(CategoryDO.class);
		queryWrapper.eq(CategoryDO::getCategoryId, categoryDestroyCmd.getCategoryId());
		queryWrapper.eq(CategoryDO::getType, categoryDestroyCmd.getType());

		queryWrapper.last("limit 1");
		CategoryDO categoryDO = categoryMapper.selectOne(queryWrapper);
		if (Objects.isNull(categoryDO)) {
			throw new BizException("400", "分类不存在，无法删除");
		}

		LambdaQueryWrapper<CategoryDO> queryWrapper1 = Wrappers.lambdaQuery(CategoryDO.class);
		queryWrapper1.eq(CategoryDO::getPid, categoryDestroyCmd.getCategoryId());
		if (categoryMapper.selectCount(queryWrapper1) > 0) {
			throw new BizException("400", "分类下存在子分类，无法删除");
		}

		categoryDO.deleteById();
	}
}
