
package com.anjiplus.template.gaea.business.modules.dataSet.service.impl;

import com.alibaba.fastjson.JSONArray;
import com.alibaba.fastjson.JSONObject;
import com.anji.plus.gaea.constant.Enabled;
import com.anji.plus.gaea.curd.mapper.GaeaBaseMapper;
import com.anji.plus.gaea.exception.BusinessExceptionBuilder;
import com.anji.plus.gaea.utils.GaeaBeanUtils;
import com.anjiplus.template.gaea.business.code.ResponseCode;
import com.anjiplus.template.gaea.business.modules.dataSet.controller.dto.OriginalDataDto;
import com.anjiplus.template.gaea.business.modules.dataSet.controller.dto.DataSetDto;
import com.anjiplus.template.gaea.business.modules.dataSet.dao.DataSetMapper;
import com.anjiplus.template.gaea.business.modules.dataSet.dao.entity.DataSet;
import com.anjiplus.template.gaea.business.modules.dataSet.service.DataSetService;
import com.anjiplus.template.gaea.business.modules.dataSetParam.controller.dto.DataSetParamDto;
import com.anjiplus.template.gaea.business.modules.dataSetParam.dao.entity.DataSetParam;
import com.anjiplus.template.gaea.business.modules.dataSetParam.service.DataSetParamService;
import com.anjiplus.template.gaea.business.modules.dataSetTransform.controller.dto.DataSetTransformDto;
import com.anjiplus.template.gaea.business.modules.dataSetTransform.dao.entity.DataSetTransform;
import com.anjiplus.template.gaea.business.modules.dataSetTransform.service.DataSetTransformService;
import com.anjiplus.template.gaea.business.modules.dataSource.controller.dto.DataSourceDto;
import com.anjiplus.template.gaea.business.modules.dataSource.dao.entity.DataSource;
import com.anjiplus.template.gaea.business.modules.dataSource.service.DataSourceService;
import com.baomidou.mybatisplus.core.conditions.query.LambdaQueryWrapper;
import com.baomidou.mybatisplus.core.conditions.query.QueryWrapper;
import com.baomidou.mybatisplus.core.toolkit.Wrappers;
import lombok.extern.slf4j.Slf4j;
import org.apache.commons.lang3.StringUtils;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

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

/**
* @desc DataSet 数据集服务实现
* @author Raod
* @date 2021-03-18 12:11:31.150755900
**/
@Service
//@RequiredArgsConstructor
@Slf4j
public class DataSetServiceImpl implements DataSetService {

    @Autowired
    private DataSetMapper dataSetMapper;

    @Autowired
    private DataSetParamService dataSetParamService;

    @Autowired
    private DataSetTransformService dataSetTransformService;

    @Autowired
    private DataSourceService dataSourceService;

    @Override
    public GaeaBaseMapper<DataSet> getMapper() {
      return dataSetMapper;
    }

    /**
     * 单条详情
     *
     * @param id
     * @return
     */
    @Override
    public DataSetDto detailSet(Long id) {
        DataSetDto dto = new DataSetDto();
        DataSet result = selectOne(id);
        String setCode = result.getSetCode();
        GaeaBeanUtils.copyAndFormatter(result, dto);
        return getDetailSet(dto, setCode);
    }

    /**
     * 单条详情
     *
     * @param setCode
     * @return
     */
    @Override
    public DataSetDto detailSet(String setCode) {
        DataSetDto dto = new DataSetDto();
        DataSet result = selectOne("set_code", setCode);
        GaeaBeanUtils.copyAndFormatter(result, dto);
        return getDetailSet(dto, setCode);
    }

    public DataSetDto getDetailSet(DataSetDto dto, String setCode) {
        //查询参数
        List<DataSetParam> dataSetParamList = dataSetParamService.list(
                new QueryWrapper<DataSetParam>()
                        .lambda()
                        .eq(DataSetParam::getSetCode, setCode)
        );
        List<DataSetParamDto> dataSetParamDtoList = new ArrayList<>();
        dataSetParamList.forEach(dataSetParam -> {
            DataSetParamDto dataSetParamDto = new DataSetParamDto();
            GaeaBeanUtils.copyAndFormatter(dataSetParam, dataSetParamDto);
            dataSetParamDtoList.add(dataSetParamDto);
        });
        dto.setDataSetParamDtoList(dataSetParamDtoList);

        //数据转换

        List<DataSetTransform> dataSetTransformList = dataSetTransformService.list(
                new QueryWrapper<DataSetTransform>()
                    .lambda()
                    .eq(DataSetTransform::getSetCode, setCode)
                    .orderByAsc(DataSetTransform::getOrderNum)
        );
        List<DataSetTransformDto> dataSetTransformDtoList = new ArrayList<>();
        dataSetTransformList.forEach(dataSetTransform -> {
            DataSetTransformDto dataSetTransformDto = new DataSetTransformDto();
            GaeaBeanUtils.copyAndFormatter(dataSetTransform, dataSetTransformDto);
            dataSetTransformDtoList.add(dataSetTransformDto);
        });
        dto.setDataSetTransformDtoList(dataSetTransformDtoList);

        if (StringUtils.isNotBlank(dto.getCaseResult())) {
            try {
                JSONArray jsonArray = JSONArray.parseArray(dto.getCaseResult());
                JSONObject jsonObject = jsonArray.getJSONObject(0);
                dto.setSetParamList(jsonObject.keySet());
            } catch (Exception e) {
                log.error("error",e);
            }
        }
        return dto;
    }


    /**
     * 新增数据集、添加查询参数、数据转换
     *
     * @param dto
     */
    @Override
    @Transactional
    public DataSetDto insertSet(DataSetDto dto) {
        List<DataSetParamDto> dataSetParamDtoList = dto.getDataSetParamDtoList();
        List<DataSetTransformDto> dataSetTransformDtoList = dto.getDataSetTransformDtoList();

        //1.新增数据集
        DataSet dataSet = new DataSet();
        BeanUtils.copyProperties(dto, dataSet);
        insert(dataSet);
        //2.更新查询参数
        dataSetParamBatch(dataSetParamDtoList, dto.getSetCode());

        //3.更新数据转换
        dataSetTransformBatch(dataSetTransformDtoList, dto.getSetCode());
        return dto;
    }

    /**
     * 更新数据集、添加查询参数、数据转换
     *
     * @param dto
     */
    @Override
    @Transactional
    public void updateSet(DataSetDto dto) {
        List<DataSetParamDto> dataSetParamDtoList = dto.getDataSetParamDtoList();
        List<DataSetTransformDto> dataSetTransformDtoList = dto.getDataSetTransformDtoList();
        //1.更新数据集
        DataSet dataSet = new DataSet();
        BeanUtils.copyProperties(dto, dataSet);
        update(dataSet);

        //2.更新查询参数
        dataSetParamBatch(dataSetParamDtoList, dto.getSetCode());

        //3.更新数据转换
        dataSetTransformBatch(dataSetTransformDtoList, dto.getSetCode());
    }


    /**
     * 删除数据集、添加查询参数、数据转换
     *
     * @param id
     */
    @Override
    public void deleteSet(Long id) {
        DataSet dataSet = selectOne(id);
        String setCode = dataSet.getSetCode();
        //1.删除数据集
        deleteById(id);

        //2.删除查询参数
        dataSetParamService.delete(
                new QueryWrapper<DataSetParam>()
                        .lambda()
                        .eq(DataSetParam::getSetCode, setCode)
        );

        //3.删除数据转换
        dataSetTransformService.delete(
                new QueryWrapper<DataSetTransform>()
                        .lambda()
                        .eq(DataSetTransform::getSetCode, setCode)
        );
    }

    /**
     * 获取数据
     *
     * @param dto
     * @return
     */
    @Override
    public OriginalDataDto getData(DataSetDto dto) {
        OriginalDataDto originalDataDto = new OriginalDataDto();
        String setCode = dto.getSetCode();
        //1.获取数据集、参数替换、数据转换
        DataSetDto dataSetDto = detailSet(setCode);
        //2.获取数据源
        DataSource dataSource = dataSourceService.selectOne("source_code", dataSetDto.getSourceCode());
        //3.参数替换
        //3.1参数校验
        boolean verification = dataSetParamService.verification(dataSetDto.getDataSetParamDtoList(), dto.getContextData());
        if (!verification) {
            throw BusinessExceptionBuilder.build(ResponseCode.RULE_FIELDS_CHECK_ERROR);
        }
        String dynSentence = dataSetParamService.transform(dto.getContextData(), dataSetDto.getDynSentence());
        //4.获取数据
        DataSourceDto dataSourceDto = new DataSourceDto();
        BeanUtils.copyProperties(dataSource, dataSourceDto);
        dataSourceDto.setDynSentence(dynSentence);
        dataSourceDto.setContextData(dto.getContextData());
        //获取total,判断contextData中是否传入分页参数
        if (null != dto.getContextData()
                && dto.getContextData().containsKey("pageNumber")
                && dto.getContextData().containsKey("pageSize")) {
            long total = dataSourceService.total(dataSourceDto, dto);
            originalDataDto.setTotal(total);
        }
        List<JSONObject> data = dataSourceService.execute(dataSourceDto);
        //5.数据转换
        List<JSONObject> transform = dataSetTransformService.transform(dataSetDto.getDataSetTransformDtoList(), data);
        originalDataDto.setData(transform);
        return originalDataDto;
    }

    /**
     * @param dto
     * @return
     */
    @Override
    public OriginalDataDto testTransform(DataSetDto dto) {
        OriginalDataDto originalDataDto = new OriginalDataDto();
        String sourceCode = dto.getSourceCode();
        //1.获取数据源
        DataSource dataSource = dataSourceService.selectOne("source_code", sourceCode);
        //3.参数替换
        //3.1参数校验
        boolean verification = dataSetParamService.verification(dto.getDataSetParamDtoList(), null);
        if (!verification) {
            throw BusinessExceptionBuilder.build(ResponseCode.RULE_FIELDS_CHECK_ERROR);
        }

        String dynSentence = dataSetParamService.transform(dto.getDataSetParamDtoList(), dto.getDynSentence());
        //4.获取数据
        DataSourceDto dataSourceDto = new DataSourceDto();
        BeanUtils.copyProperties(dataSource, dataSourceDto);
        dataSourceDto.setDynSentence(dynSentence);
        dataSourceDto.setContextData(dto.getContextData());

        //获取total,判断DataSetParamDtoList中是否传入分页参数
        Map<String, Object> collect = dto.getDataSetParamDtoList().stream().collect(Collectors.toMap(DataSetParamDto::getParamName, DataSetParamDto::getSampleItem));
        if (collect.containsKey("pageNumber") && collect.containsKey("pageSize")) {
            dto.setContextData(collect);
            long total = dataSourceService.total(dataSourceDto, dto);
            originalDataDto.setTotal(total);
        }

        List<JSONObject> data = dataSourceService.execute(dataSourceDto);
        //5.数据转换
        List<JSONObject> transform = dataSetTransformService.transform(dto.getDataSetTransformDtoList(), data);
        originalDataDto.setData(transform);
        return originalDataDto;
    }


    /**
     * 获取所有数据集
     *
     * @return
     */
    @Override
    public List<DataSet> queryAllDataSet() {
        LambdaQueryWrapper<DataSet> wrapper = Wrappers.lambdaQuery();
        wrapper.select(DataSet::getSetCode, DataSet::getSetName, DataSet::getSetDesc, DataSet::getId)
                .eq(DataSet::getEnableFlag, Enabled.YES.getValue());
        return dataSetMapper.selectList(wrapper);
    }

    public void dataSetParamBatch(List<DataSetParamDto> dataSetParamDtoList,String setCode){
        dataSetParamService.delete(
                new QueryWrapper<DataSetParam>()
                        .lambda()
                        .eq(DataSetParam::getSetCode, setCode)
        );
        if (null == dataSetParamDtoList || dataSetParamDtoList.size() <= 0) {
            return;
        }
        List<DataSetParam> dataSetParamList = new ArrayList<>();
        dataSetParamDtoList.forEach(dataSetParamDto -> {
            DataSetParam dataSetParam = new DataSetParam();
            BeanUtils.copyProperties(dataSetParamDto, dataSetParam);
            dataSetParam.setSetCode(setCode);
            dataSetParamList.add(dataSetParam);
        });
        dataSetParamService.insertBatch(dataSetParamList);

    }

    public void dataSetTransformBatch(List<DataSetTransformDto> dataSetTransformDtoList,String setCode){
        dataSetTransformService.delete(
                new QueryWrapper<DataSetTransform>()
                        .lambda()
                        .eq(DataSetTransform::getSetCode, setCode)
        );
        if (null == dataSetTransformDtoList || dataSetTransformDtoList.size() <= 0) {
            return;
        }
        List<DataSetTransform> dataSetTransformList = new ArrayList<>();
        for (int i = 0; i < dataSetTransformDtoList.size(); i++) {
            DataSetTransform dataSetTransform = new DataSetTransform();
            BeanUtils.copyProperties(dataSetTransformDtoList.get(i), dataSetTransform);
            dataSetTransform.setOrderNum(i + 1);
            dataSetTransform.setSetCode(setCode);
            dataSetTransformList.add(dataSetTransform);
        }
        dataSetTransformService.insertBatch(dataSetTransformList);
    }

}
