package cn.stylefeng.team.meta.modular.service.common;

import cn.hutool.core.collection.ListUtil;
import cn.hutool.core.util.ObjectUtil;
import cn.stylefeng.team.meta.api.entity.MetaModel;
import cn.stylefeng.team.meta.api.enums.MetaModelTypeEnum;
import cn.stylefeng.team.meta.modular.mapper.MetaModelMapper;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.extension.service.impl.ServiceImpl;
import org.springframework.stereotype.Service;

import java.io.Serializable;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;
import java.util.stream.Collectors;

@Service
public class BaseMetaModelService extends ServiceImpl<MetaModelMapper, MetaModel> {

    @Override
    public MetaModel getById(Serializable id) {
        MetaModel metaModel = super.getById(id);
        if(metaModel == null){
            return null;
        }

        return processOuterDefinition(ListUtil.of(metaModel)).get(0);
    }

    @Override
    public List<MetaModel> list(Wrapper<MetaModel> queryWrapper) {

        List<MetaModel> list = super.list(queryWrapper);
        if (ObjectUtil.isEmpty(list)) {
            return list;
        }

        return processOuterDefinition(list);
    }

    @Override
    public MetaModel getOne(Wrapper<MetaModel> queryWrapper, boolean throwEx) {
        MetaModel metaModel = super.getOne(queryWrapper, throwEx);
        if (metaModel == null) {
            return null;
        }

        return processOuterDefinition(List.of(metaModel)).get(0);
    }

    @Override
    public MetaModel getOne(Wrapper<MetaModel> queryWrapper) {
        return this.getOne(queryWrapper, true);
    }

    private List<MetaModel> processOuterDefinition(List<MetaModel> lastResult) {

        List<MetaModel> needGetOuterDefinitionModelList = new ArrayList<>();
        for (MetaModel metaModel : lastResult) {
            if (ObjectUtil.isEmpty(metaModel.getMetaModelType())
                    || MetaModelTypeEnum.NEW_MODEL.getCode().equals(metaModel.getMetaModelType())) {
                continue;
            }
            if (metaModel.getLinkModelId() == null) {
                continue;
            }
            needGetOuterDefinitionModelList.add(metaModel);
        }

        if (ObjectUtil.isEmpty(needGetOuterDefinitionModelList)) {
            return lastResult;
        }

        Set<Long> linkModelIdList = needGetOuterDefinitionModelList.stream().map(MetaModel::getLinkModelId).collect(Collectors.toSet());
        LambdaQueryWrapper<MetaModel> wrapper = new LambdaQueryWrapper<>();
        wrapper.in(MetaModel::getMetaModelId, linkModelIdList);
        List<MetaModel> linkModelList = super.list(wrapper);

        for (MetaModel needGetOuterDefinitionModel : needGetOuterDefinitionModelList) {
            for (MetaModel linkModel : linkModelList) {
                if (needGetOuterDefinitionModel.getLinkModelId().equals(linkModel.getMetaModelId())) {
                    needGetOuterDefinitionModel.setCurrentDefinitionId(linkModel.getCurrentDefinitionId());
                }
            }
        }

        return lastResult;
    }

}