package com.docus.server.service.impl;

import com.docus.core.util.Func;
import com.docus.core.util.ListUtils;
import com.docus.core.util.property.Setters;
import com.docus.infrastructure.redis.service.IdService;
import com.docus.infrastructure.web.exception.ApiException;
import com.docus.infrastructure.web.exception.ExceptionCode;
import com.docus.infrastructure.web.request.SearchDTO;
import com.docus.infrastructure.web.response.PageResult;
import com.docus.log.annotation.TrackGroup;
import com.docus.server.common.process.TcpProcessor;
import com.docus.server.convert.SchCollectorConvert;
import com.docus.server.dto.scheduling.management.schcollector.AddSchCollectorDTO;
import com.docus.server.dto.scheduling.management.schcollector.DeleteSchCollectorDTO;
import com.docus.server.dto.scheduling.management.schcollector.EditSchCollectorDTO;
import com.docus.server.dto.scheduling.management.schcollector.UpdateSchCollectorDTO;
import com.docus.server.entity.scheduling.management.SchCollector;
import com.docus.server.entity.scheduling.management.SchCollectorVersion;
import com.docus.server.entity.scheduling.management.SchCollectorVersionFile;
import com.docus.server.entity.scheduling.management.SchSystemParams;
import com.docus.server.infrastructure.dao.ISchCollectorDao;
import com.docus.server.infrastructure.dao.ISchCollectorVersionDao;
import com.docus.server.infrastructure.dao.ISchCollectorVersionFileDao;
import com.docus.server.service.ISchCollectorService;
import com.docus.server.service.ISchSystemParamsService;
import com.docus.server.vo.scheduling.management.schcollector.LoadSchCollectorVO;
import com.docus.server.vo.scheduling.management.schcollector.SchCollectorVO;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import org.springframework.util.CollectionUtils;

import javax.annotation.Resource;
import java.util.ArrayList;
import java.util.Comparator;
import java.util.Date;
import java.util.List;
import java.util.Map;
import java.util.Optional;
import java.util.stream.Collectors;

/**
 * 采集器管理 服务实现类
 *
 * @author AutoGenerator
 * @since 2023-07-15
 */
@Service
public class SchCollectorServiceImpl implements ISchCollectorService {
    @Resource
    private ISchCollectorDao iSchCollectorDao;
    @Resource
    private ISchCollectorVersionDao iSchCollectorVersionDao;
    @Resource
    private ISchCollectorVersionFileDao iSchCollectorVersionFileDao;
    @Resource
    private ISchSystemParamsService iSchSystemParamsService;
    @Resource
    private IdService idService;

    /**
     * 按主键查询
     *
     * @param id 主键Id
     * @return 实体
     */
    @Override
    public SchCollectorVO findById(String id) {
        return SchCollectorConvert.INSTANCE.convertVO(iSchCollectorDao.findById(id));
    }

    /**
     * 关键字搜索
     *
     * @param searchDTO 搜索参数
     * @return 分页列表
     */
    @Override
    public PageResult<SchCollectorVO> search(SearchDTO searchDTO) {
        PageResult<SchCollectorVO> result = SchCollectorConvert.INSTANCE.convertVO(iSchCollectorDao.search(searchDTO));

        if (CollectionUtils.isEmpty(result.getList())) {
            return new PageResult<>();
        }

        Map<String, SchSystemParams> map = iSchSystemParamsService.find(ListUtils.distinctSelect(result.getList(), SchCollectorVO::getCollectorId));

        Setters.<SchCollectorVO>instance().list(result.getList()).cycleSetProperties(p -> {
            String collectorId = String.valueOf(p.getCollectorId());
            if (map.containsKey(collectorId)) {
                p.setCollectorName(map.get(collectorId).getParamName());
            }
        });

        return result;
    }

    /**
     * 选为当前版本并更新
     *
     * @return 成功或失败
     */
    @TrackGroup(group = "SchCollectorServiceImpl", processor = TcpProcessor.class)
    @Transactional(rollbackFor = Exception.class)
    @Override
    public boolean updateVersion(UpdateSchCollectorDTO updateDTO) {
        SchCollector schCollector = iSchCollectorDao.findOneBy("collectorId", updateDTO.getCollectorId());
        schCollector.setCollectorVersionId(updateDTO.getCollectorVersionId());
        return iSchCollectorDao.updateById(schCollector);
    }

    @Override
    public SchCollector findByCollectorId(String collectorId) {
        return iSchCollectorDao.findOneBy("collectorId", collectorId);
    }

    @Override
    public List<LoadSchCollectorVO> findAll() {
        List<SchCollector> schCollectors = iSchCollectorDao.findAll();

        List<SchCollectorVersion> schCollectorVersionList = iSchCollectorVersionDao.findAll();

        List<SchCollectorVersionFile> schCollectorVersionFileList = iSchCollectorVersionFileDao.findAll();

        List<SchCollector> notEmptyVersionCollectors = schCollectors.stream().filter(p -> Func.isNotEmpty(p.getCollectorVersionId())).collect(Collectors.toList());

        List<SchCollector> emptyVersionCollectors = schCollectors.stream().filter(p -> Func.isEmpty(p.getCollectorVersionId())).collect(Collectors.toList());

        Map<String, SchCollectorVersionFile> stringSchCollectorVersionFileMap = ListUtils.toMap(schCollectorVersionFileList, schCollectorVersionFile -> String.format("%s%s", schCollectorVersionFile.getCollectorId(), schCollectorVersionFile.getCollectorVersionId()));

        List<LoadSchCollectorVO> loadSchCollectorVOList = new ArrayList<>();

        for (SchCollector schCollector : notEmptyVersionCollectors) {
            String key = String.format("%s%s", schCollector.getCollectorId(), schCollector.getCollectorVersionId());
            if (stringSchCollectorVersionFileMap.containsKey(key)) {
                LoadSchCollectorVO loadSchCollectorVO = new LoadSchCollectorVO();

                SchCollectorVersionFile schCollectorVersionFile = stringSchCollectorVersionFileMap.get(key);
                loadSchCollectorVO.setCollectorId(schCollector.getCollectorId());
                loadSchCollectorVO.setCollectorVersionId(schCollectorVersionFile.getCollectorVersionId());
                loadSchCollectorVO.setFilePath(schCollectorVersionFile.getFilePath());
                loadSchCollectorVO.setDeployPath(schCollectorVersionFile.getDeployPath());
                loadSchCollectorVO.setProcessName(schCollectorVersionFile.getProcessName());

                loadSchCollectorVOList.add(loadSchCollectorVO);
            }
        }

        Map<Long, Optional<SchCollectorVersion>> collectorVersionMap = schCollectorVersionList.stream().collect(Collectors.groupingBy(SchCollectorVersion::getCollectorId, Collectors.maxBy(Comparator.comparing(SchCollectorVersion::getCollectVersion))));

        for (SchCollector schCollector : emptyVersionCollectors) {
            Long key = schCollector.getCollectorId();

            if (collectorVersionMap.containsKey(key)) {

                SchCollectorVersion schCollectorVersion = collectorVersionMap.get(key).get();

                String versionKey = String.format("%s%s", schCollectorVersion.getCollectorId(), schCollectorVersion.getId());

                if (stringSchCollectorVersionFileMap.containsKey(versionKey)) {

                    LoadSchCollectorVO loadSchCollectorVO = new LoadSchCollectorVO();

                    SchCollectorVersionFile schCollectorVersionFile = stringSchCollectorVersionFileMap.get(versionKey);

                    loadSchCollectorVO.setCollectorId(schCollector.getCollectorId());
                    loadSchCollectorVO.setCollectorVersionId(schCollectorVersionFile.getCollectorVersionId());
                    loadSchCollectorVO.setFilePath(schCollectorVersionFile.getFilePath());
                    loadSchCollectorVO.setDeployPath(schCollectorVersionFile.getDeployPath());
                    loadSchCollectorVO.setProcessName(schCollectorVersionFile.getProcessName());

                    loadSchCollectorVOList.add(loadSchCollectorVO);
                }

            }
        }
        return loadSchCollectorVOList;
    }

    /**
     * 新增
     *
     * @param addSchCollectorDTO 编辑参数
     * @return 成功或失败
     */
    @Override
    public boolean add(AddSchCollectorDTO addSchCollectorDTO) {

        Long collectorId = addSchCollectorDTO.getCollectorId();

        SchCollector schCollectorDO = iSchCollectorDao.findOneBy("collectorId", collectorId);

        if (Func.notNull(schCollectorDO)) {
            throw new ApiException(ExceptionCode.ParamIllegal.getCode(), "采集器类型已经存在");
        }

        SchCollector schCollector = SchCollectorConvert.INSTANCE.convertDO(addSchCollectorDTO);
        schCollector.setId(idService.getDateSeq());
        return iSchCollectorDao.add(schCollector);
    }

    /**
     * 编辑
     *
     * @param editSchCollectorDTO 编辑参数
     * @return 成功或失败
     */
    @Override
    public boolean edit(EditSchCollectorDTO editSchCollectorDTO) {

        Long id = editSchCollectorDTO.getId();

        SchCollector schCollector = iSchCollectorDao.findById(id);

        if (Func.isNull(schCollector)) {
            throw new ApiException(ExceptionCode.ParamIllegal.getCode(), "采集器不存在，无法更新");
        }

        schCollector.setCollectLanguage(editSchCollectorDTO.getCollectLanguage());
        schCollector.setStartMode(editSchCollectorDTO.getStartMode());
        schCollector.setTaskTimeout(editSchCollectorDTO.getTaskTimeout());
        schCollector.setUpdateTime(new Date());
        return iSchCollectorDao.edit(schCollector);
    }

    /**
     * 批量删除
     *
     * @param deleteSchCollectorDTO 删除参数
     * @return 成功或失败
     */
    @Override
    public int delete(DeleteSchCollectorDTO deleteSchCollectorDTO) {
        return iSchCollectorDao.delete(deleteSchCollectorDTO.getIds());
    }
}

