package com.persagy.dmp.codetable.service.impl;

import cn.hutool.core.collection.CollUtil;
import cn.hutool.core.util.StrUtil;
import com.baomidou.mybatisplus.core.conditions.Wrapper;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.persagy.dmp.basic.dto.RequestData;
import com.persagy.dmp.codetable.dao.CodeTableDataMapper;
import com.persagy.dmp.codetable.entity.CodeTableData;
import com.persagy.dmp.codetable.entity.CodeTableType;
import com.persagy.dmp.codetable.service.ICodeTableDataService;
import com.persagy.dmp.codetable.service.ICodeTableTypeService;
import com.persagy.dmp.common.constant.ValidEnum;
import com.persagy.dmp.common.exception.BusinessException;
import com.persagy.dmp.common.model.entity.BaseEntity;
import com.persagy.dmp.mybatis.utils.ConditionUtil;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

import javax.annotation.Resource;
import java.util.*;
import java.util.stream.Collectors;

/**
 * 码表数据 实现类
 * @author Charlie Yu
 * @date 2021-07-27
 */
@Service
@Transactional(rollbackFor = Exception.class)
public class CodeTableDataServiceImpl implements ICodeTableDataService {

    @Resource
    private CodeTableDataMapper dao;
    @Autowired
    private ICodeTableTypeService typeService;

    @Override
    public CodeTableData insert(CodeTableData vo) {
        dao.insert(vo);
        return vo;
    }

    @Override
    public CodeTableData update(CodeTableData vo) {
        dao.updateById(vo);
        return vo;
    }

    @Override
    public void delete(String id) {
        CodeTableData vo = load(id);
        if(vo == null) {
            throw new BusinessException("找不到对应的数据！");
        }
        vo.setValid(ValidEnum.FALSE.getType());
        dao.updateById(vo);
    }

    @Override
    public CodeTableData load(String id) {
        return dao.selectById(id);
    }

    @Override
    public List<CodeTableData> queryByCondition(Wrapper<CodeTableData> queryWrapper) {
        return dao.selectList(queryWrapper);
    }

    @Override
    public List<CodeTableData> queryAllByTypeCode(String projectId, String typeCode) {
        CodeTableType codeType = typeService.loadByCode(projectId, typeCode);
        if(codeType == null) {
            return null;
        }
        List<CodeTableData> dataList = commonQueryCodeTableDatasByTypeCode(codeType,projectId);
        if(CollUtil.isEmpty(dataList)) {
            return null;
        } else if(!codeType.isTree()) {
            // 列表结构直接返回即可
            return dataList;
        }
        // 转换为树型
        Map<String, CodeTableData> dataMap = CollUtil.fieldValueMap(dataList, BaseEntity.PROP_ID);
        List<CodeTableData> rsList = new ArrayList<>();
        for(CodeTableData data:dataList) {
            String parentId = data.getParentId();
            // 如果找不到上级节点，直接添加到结果列表中
            if(StrUtil.isBlank(parentId) || dataMap.get(parentId) == null) {
                rsList.add(data);
                continue;
            }
            // 能找到上级节点，则放入上级节点的子节点列表中
            CodeTableData parent = dataMap.get(parentId);
            if(parent.getContent() == null) {
                parent.setContent(new ArrayList<>());
            }
            parent.getContent().add(data);
        }
        return rsList;
    }

    /**
     * 通过类型和code查询所有码表数据
     * @param projectId 项目ID
     * @param typeCode 码表类型编码
     * @return 码表数据。如果为树型，则返回树型结果
     */
    @Override
    public List<CodeTableData> queryCodeTableDatasByTypeCodeAndCodes(String projectId, String typeCode,
                                                                     RequestData requestData) {
        CodeTableType codeType = typeService.loadByCode(projectId, typeCode);
        if(null == codeType) {
            return new ArrayList<>();
        }
        List<CodeTableData> codeTableDatas = commonQueryCodeTableDatasByTypeCode(codeType, projectId);
        if (CollUtil.isEmpty(codeTableDatas)){
            return new ArrayList<>();
        }
        if (CollUtil.isNotEmpty(requestData.getCodes())){
            return codeTableDatas.stream()
                    .filter(codeTableData -> requestData.getCodes().contains(codeTableData.getCode()))
                    .collect(Collectors.toList());
        }
        return codeTableDatas;
    }
    /***
     * Description: 根据父码表code查询其下的码表数据
     * @param projectId : 项目id
     * @param requestData : 请求参数
     * @return : java.util.List<com.persagy.dmp.codetable.entity.CodeTableData>
     * @author : lijie
     * @date :2021/8/30 22:58
     * Update By lijie 2021/8/30 22:58
     */
    @Override
    public List<CodeTableData> queryCodeTableDatasByParentCode(String projectId, RequestData requestData) {
        // 1.查询对应码表类型值
        CodeTableType codeType = typeService.loadByCode(projectId, requestData.getTypeCode());
        if(null == codeType) {
            return new ArrayList<>();
        }
        // 2.根据码表类型和项目id查询码表数据
        List<CodeTableData> codeTableDatas = commonQueryCodeTableDatasByTypeCode(codeType, projectId);
        if (CollUtil.isEmpty(codeTableDatas)){
            return new ArrayList<>();
        }
        // 3.获取符合条件的父级对象
        Optional<CodeTableData> parentCodeData = codeTableDatas.stream()
                .filter(codeTableData -> requestData.getParentCode().equals(codeTableData.getCode()))
                .findFirst();
        if (!parentCodeData.isPresent()){
            return new ArrayList<>();
        }
        CodeTableData parentCodeTableData = parentCodeData.get();
        return codeTableDatas.stream()
                .filter(codeTableData -> codeTableData.getInnerCode().contains(parentCodeTableData.getInnerCode()))
                .sorted(Comparator.comparing(CodeTableData::getInnerCode))
                .collect(Collectors.toList());
    }

    /***
     * Description: 通用的根据typeCode查询数据
     * @param projectId : 项目id
     * @param codeType : 码表类型对象
     * @return : java.util.List<com.persagy.dmp.codetable.entity.CodeTableData>
     * @author : lijie
     * @date :2021/8/30 22:41
     * Update By lijie 2021/8/30 22:41
     */
    private List<CodeTableData> commonQueryCodeTableDatasByTypeCode(CodeTableType codeType,String projectId){

        LambdaQueryWrapper<CodeTableData> wrapper = new LambdaQueryWrapper<>();
        wrapper.select(CodeTableData::getId, CodeTableData::getParentId,
                CodeTableData::getCode, CodeTableData::getName, CodeTableData::getExtras,CodeTableData::getInnerCode);
        wrapper.eq(CodeTableData::getTypeId, codeType.getId());
        wrapper.eq(CodeTableData::getValid, ValidEnum.TRUE.getType());
        ConditionUtil.ensureProjectCriteria(wrapper, CodeTableData::getProjectId, projectId);
        wrapper.orderByAsc(CodeTableData::getShowOrder);
        return dao.selectList(wrapper);
    }


}
