package cn.iocoder.yudao.module.system.service.biz;

import cn.hutool.core.collection.CollectionUtil;
import cn.iocoder.yudao.framework.common.pojo.PageResult;
import cn.iocoder.yudao.framework.mybatis.core.query.LambdaQueryWrapperX;
import cn.iocoder.yudao.module.system.controller.admin.sys.vo.SysChargeCategoryPageReqVO;
import cn.iocoder.yudao.module.system.dal.dataobject.biz.SysChargeCategoryDO;
import cn.iocoder.yudao.module.system.dal.dataobject.tenant.TenantDO;
import cn.iocoder.yudao.module.system.dal.mysql.biz.SysChargeCategoryMapper;
import cn.iocoder.yudao.module.system.dal.mysql.tenant.TenantMapper;
import cn.iocoder.yudao.module.system.enums.ErrorCodeConstants;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.validation.annotation.Validated;

import javax.annotation.Resource;
import java.util.Comparator;
import java.util.List;
import java.util.stream.Collectors;

import static cn.iocoder.yudao.framework.common.exception.util.ServiceExceptionUtil.exception;

@Service
@Validated
@Slf4j
public class SysChargeCategoryServiceImpl implements SysChargeCategoryService {

    @Resource
    private SysChargeCategoryMapper sysChargeCategoryMapper;
    @Resource
    private TenantMapper tenantMapper;

    @Override
    public void add(SysChargeCategoryDO sysChargeCategory) {
        sysChargeCategory.setParentId(sysChargeCategory.getParentId() == null ? 0 : sysChargeCategory.getParentId());
        sysChargeCategoryMapper.insert(sysChargeCategory);
    }

    @Override
    public PageResult<SysChargeCategoryDO> findPage(SysChargeCategoryPageReqVO pageReqVO) {
        Page<SysChargeCategoryDO> page = new Page<>(pageReqVO.getPageNo(), pageReqVO.getPageSize());
        List<SysChargeCategoryDO> list = sysChargeCategoryMapper.findPage(page, pageReqVO);
        for (SysChargeCategoryDO sysChargeCategoryDO : list) {
            TenantDO tenantDO = tenantMapper.selectById(sysChargeCategoryDO.getTenantId());
            sysChargeCategoryDO.setTenantName(tenantDO.getName());
        }
        return new PageResult<>(list, page.getTotal());
    }

    @Override
    public SysChargeCategoryDO getInfoById(Long id) {
        return sysChargeCategoryMapper.selectById(id);
    }

    @Override
    public void edit(SysChargeCategoryDO sysChargeCategory) {
        sysChargeCategoryMapper.updateById(sysChargeCategory);
    }

    @Override
    public void delete(Long id) {
        SysChargeCategoryDO sysChargeCategoryDO = sysChargeCategoryMapper.selectById(id);
        if (sysChargeCategoryDO != null) {
            List<SysChargeCategoryDO> sysChargeCategoryEntities = sysChargeCategoryMapper.selectList(new LambdaQueryWrapper<SysChargeCategoryDO>()
                    .eq(SysChargeCategoryDO::getParentId, sysChargeCategoryDO.getId()));

            if (CollectionUtil.isNotEmpty(sysChargeCategoryEntities)) {
                throw exception(ErrorCodeConstants.COMMON_ERROR);
            }
            sysChargeCategoryMapper.deleteById(id);
        }
    }

    @Override
    public SysChargeCategoryDO getTreeById(Long id) {
        SysChargeCategoryDO sysChargeCategory = sysChargeCategoryMapper.selectById(id);
        List<SysChargeCategoryDO> list = sysChargeCategoryMapper.selectList(null);
        sysChargeCategory.setChildrenList(getAllSubNodes(sysChargeCategory, list));
        return sysChargeCategory;
    }

    private List<SysChargeCategoryDO> getAllSubNodes(SysChargeCategoryDO rootNode, List<SysChargeCategoryDO> list) {
        if (CollectionUtil.isEmpty(list)) {
            return null;
        }
        return list.stream().filter(item -> item.getParentId().equals(rootNode.getId())).peek(menu -> menu.setChildrenList(getAllSubNodes(menu, list))).sorted(Comparator.comparing(SysChargeCategoryDO::getSort))
                .collect(Collectors.toList());
    }

    @Override
    public List<SysChargeCategoryDO> getTree(Long[] tenantIds, Integer orgType, Integer type) {
        List<SysChargeCategoryDO> parentList = sysChargeCategoryMapper.selectList(new LambdaQueryWrapperX<SysChargeCategoryDO>()
                .eq(SysChargeCategoryDO::getParentId, 0)
                .inIfPresent(SysChargeCategoryDO::getTenantId,tenantIds)
                .eqIfPresent(SysChargeCategoryDO::getOrgType,orgType)
                .eqIfPresent(SysChargeCategoryDO::getType, type));
        List<SysChargeCategoryDO> dataList = parentList.stream().map(item -> this.getTreeById(item.getId())).sorted(Comparator.comparing(SysChargeCategoryDO::getSort)).collect(Collectors.toList());

        return dataList;
    }
}
