package com.persagy.dmp.rwd.digital.service.calstrategy;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.extension.plugins.pagination.Page;
import com.persagy.dmp.basic.dto.RelExtendCalDTO;
import com.persagy.dmp.basic.dto.RelationCalRuleDTO;
import com.persagy.dmp.basic.model.QueryCriteria;
import com.persagy.dmp.basic.utils.QueryCriteriaHelper;
import com.persagy.dmp.common.constant.CommonConstant;
import com.persagy.dmp.common.model.entity.BaseEntity;
import com.persagy.dmp.digital.entity.ObjectDigital;
import com.persagy.dmp.digital.entity.ObjectRelation;
import com.persagy.dmp.rwd.basic.utils.DigitalCommonUtils;
import com.persagy.dmp.rwd.digital.domain.CalculatingDTO;
import com.persagy.dmp.rwd.digital.service.CalculateService;
import com.persagy.dmp.rwd.digital.service.IObjectDigitalService;
import com.persagy.dmp.rwd.digital.service.IObjectRelationService;
import lombok.RequiredArgsConstructor;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;

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

/***
 * Description: 通过继承某种关系生成的关系
 * @author : lijie
 * @date :2021/10/8 19:19
 * Update By lijie 2021/10/8 19:19
 */
@Service
@Slf4j
@RequiredArgsConstructor
public class RelExtendCalculateServiceImpl implements CalculateService {

    private final IObjectDigitalService objectDigitalService;
    private final IObjectRelationService objectRelationService;

    /***
     * Description: 通过继承某种关系计算关系
     * @param calRule : 计算规则
     * @param calculatingDTO : 参数
     * @return : void
     * @author : lijie
     * @date :2021/9/8 17:14
     * Update By lijie 2021/9/8 17:14
     */
    @Override
    public void calculateRelation(RelationCalRuleDTO calRule, CalculatingDTO calculatingDTO) {
        RelExtendCalDTO relExtendCal = calRule.getRelExtendCal();
        // 1.根据对象类型查询对象,分页查询
        QueryWrapper<ObjectDigital> queryWrapper = createCommonQueryWrapper(null,calculatingDTO);
        QueryCriteriaHelper.toWrapper(queryWrapper,relExtendCal.getObjFilterObj(),ObjectDigital.class);
        int count = objectDigitalService.count(queryWrapper);
        if (count<=0){
            return;
        }
        // 2.分页处理数据
        long page=(count%CommonConstant.QUERY_DEFAULT_PAGE_SIZE==0)
                ?(count/CommonConstant.QUERY_DEFAULT_PAGE_SIZE):(count/CommonConstant.QUERY_DEFAULT_PAGE_SIZE+1);
        for (long i = 0; i < page; i++) {
            // 2.1 根据分页查询数据
            Page<ObjectDigital> pageInfo = new Page<>();
            pageInfo.setCurrent(i);
            pageInfo.setSize(CommonConstant.QUERY_DEFAULT_PAGE_SIZE);
            Page<ObjectDigital> digitalPage = objectDigitalService.page(pageInfo, queryWrapper);
            if (CollUtil.isEmpty(digitalPage.getRecords())){
                continue;
            }
            List<ObjectDigital> records = digitalPage.getRecords();
            // 2.2 根据对象id生成关系
            generateRelationsByObjIds(records
                    .stream()
                    .map(BaseEntity::getId)
                    .collect(Collectors.toSet()),
                    calculatingDTO,
                    relExtendCal);
        }
    }
    /***
     * Description:  根据对象id生成关系
     * @param objIds : 对象id集合
     * @param calculatingDTO : 请求参数对象
     * @param relExtendCal : 关系定义计算器
     * @return : void
     * @author : lijie
     * @date :2021/10/8 20:13
     * Update By lijie 2021/10/8 20:13
     */
    private void generateRelationsByObjIds(Set<String> objIds, CalculatingDTO calculatingDTO,
                                           RelExtendCalDTO relExtendCal) {
        // 1.查询继承的关系
        QueryCriteria relationFilterObj = relExtendCal.getRelationFilterObj();
        QueryWrapper<ObjectRelation> queryWrapper = createCommonQueryWrapper(null,calculatingDTO);
        QueryCriteriaHelper.toWrapper(queryWrapper,relationFilterObj,ObjectRelation.class);
        if (relExtendCal.getObjSide()){
            queryWrapper.in("relFrom",objIds);
        }else {
            queryWrapper.in("relTo",objIds);
        }
        List<ObjectRelation> queryObjectRelations = objectRelationService.list(queryWrapper);
        if (CollUtil.isEmpty(queryObjectRelations)){
            return;
        }
        // 2.根据继承关系生成关系对象
        // 2.1 生成关系对象
        List<ObjectRelation> objectRelations = new ArrayList<>();
        for (ObjectRelation queryObjectRelation : queryObjectRelations) {
            ObjectRelation objectRelation = new ObjectRelation();
            objectRelation.setGroupCode(calculatingDTO.getGroupCode());
            objectRelation.setProjectId(calculatingDTO.getProjectId());
            objectRelation.setGraphCode(calculatingDTO.getGraphCode());
            objectRelation.setRelCode(calculatingDTO.getRelCode());
            objectRelation.setRelValue(calculatingDTO.getRelValue());
            objectRelation.setObjFrom(queryObjectRelation.getObjFrom());
            objectRelation.setObjTo(queryObjectRelation.getObjTo());
            objectRelations.add(objectRelation);
        }
        if (CollUtil.isNotEmpty(objectRelations)){
            // 2.2 删除对应的关系对象
            deleteRelDataByCondition(calculatingDTO,
                    objectRelations.stream().map(ObjectRelation::getObjFrom).collect(Collectors.toSet()),
                    objectRelations.stream().map(ObjectRelation::getObjTo).collect(Collectors.toSet()));
            // 2.3 保存对象关系
            objectRelationService.save(objectRelations);
        }
    }

    /***
     * Description: 根据请求参数和id集合删除关系
     * @param calculatingDTO : 请求参数
     * @param fromIds : 来源id集合
     * @param toIds : 去向id集合
     * @return : void
     * @author : lijie
     * @date :2021/9/11 16:13
     * Update By lijie 2021/9/11 16:13
     */
    private void deleteRelDataByCondition(CalculatingDTO calculatingDTO, Set<String> fromIds, Set<String> toIds) {
        fromIds.addAll(toIds);
        QueryWrapper<ObjectRelation> queryWrapper = createCommonQueryWrapper(fromIds,calculatingDTO);
        queryWrapper.eq(StrUtil.toUnderlineCase(ObjectRelation.GRAPH_CODE_HUM),calculatingDTO.getGraphCode());
        queryWrapper.eq(StrUtil.toUnderlineCase(ObjectRelation.REL_CODE_HUM),calculatingDTO.getRelCode());
        if (StrUtil.isNotBlank(calculatingDTO.getRelValue())){
            queryWrapper.eq(StrUtil.toUnderlineCase(ObjectRelation.REL_VALUE_HUM),calculatingDTO.getRelValue());
        }
        objectRelationService.delete(queryWrapper);
    }

    /***
     * Description: 创建通用查询条件对象
     * @param ids : 对象id数组
     * @param calculatingDTO : 请求参数
     * @return : com.baomidou.mybatisplus.core.conditions.query.QueryWrapper<com.persagy.dmp.digital.entity.ObjectDigital>
     * @author : lijie
     * @date :2021/9/11 15:41
     * Update By lijie 2021/9/11 15:41
     */
    private <T> QueryWrapper<T> createCommonQueryWrapper(Set<String> ids, CalculatingDTO calculatingDTO) {
        QueryWrapper<T> queryWrapper = new QueryWrapper<>();
        queryWrapper.eq(ObjectDigital.PROP_VALID,Boolean.TRUE);
        if (CollUtil.isNotEmpty(ids)){
            queryWrapper.in(ObjectDigital.PROP_ID,ids);
        }
        if (StrUtil.isNotBlank(calculatingDTO.getGroupCode())){
            queryWrapper.eq(StrUtil.toUnderlineCase(CommonConstant.QUERY_GROUPCODE),calculatingDTO.getGroupCode());
        }
        if (StrUtil.isNotBlank(calculatingDTO.getProjectId())){
            queryWrapper.eq(StrUtil.toUnderlineCase(CommonConstant.QUERY_PROJECTID),calculatingDTO.getProjectId());
        }
        return queryWrapper;
    }
}
