package cn.reghao.devops.web.mgr.app.db.query.impl;

import cn.reghao.devops.web.mgr.app.db.query.AppBuildQuery;
import cn.reghao.devops.web.mgr.app.db.repository.AppBuildingRepository;
import cn.reghao.devops.web.mgr.app.db.repository.config.AppConfigRepository;
import cn.reghao.devops.web.mgr.app.db.repository.config.AppDeployConfigRepository;
import cn.reghao.devops.web.mgr.app.db.repository.log.BuildLogRepository;
import cn.reghao.devops.web.mgr.app.model.po.AppBuilding;
import cn.reghao.devops.web.mgr.app.model.po.config.AppConfig;
import cn.reghao.devops.web.mgr.app.model.po.log.BuildLog;
import cn.reghao.devops.web.mgr.app.model.vo.AppBuildingVO;
import cn.reghao.devops.web.mgr.app.model.vo.BuildLogVO;
import cn.reghao.devops.web.mgr.builds.model.po.CompilerConfig;
import cn.reghao.devops.web.mgr.builds.model.po.PackerConfig;
import cn.reghao.devops.web.mgr.builds.model.po.RepoAuthConfig;
import cn.reghao.devops.web.mgr.app.model.vo.AppConfigVO;
import org.springframework.data.domain.Page;
import org.springframework.data.domain.PageImpl;
import org.springframework.data.domain.PageRequest;
import org.springframework.data.domain.Pageable;
import org.springframework.data.jpa.domain.Specification;
import org.springframework.stereotype.Service;

import javax.persistence.criteria.Predicate;
import java.util.ArrayList;
import java.util.List;
import java.util.Map;
import java.util.stream.Collectors;

/**
 * @author reghao
 * @date 2021-06-02 15:01:18
 */
@Service
public class AppBuildQueryImpl implements AppBuildQuery {
    private final AppConfigRepository appConfigRepository;
    private final AppDeployConfigRepository deployConfigRepository;
    private final AppBuildingRepository buildingRepository;
    private final BuildLogRepository buildLogRepository;

    public AppBuildQueryImpl(AppConfigRepository appConfigRepository, AppDeployConfigRepository deployConfigRepository,
                             AppBuildingRepository buildingRepository, BuildLogRepository buildLogRepository) {
        this.appConfigRepository = appConfigRepository;
        this.deployConfigRepository = deployConfigRepository;
        this.buildingRepository = buildingRepository;
        this.buildLogRepository = buildLogRepository;
    }

    @Override
    public AppConfig findById(int id) {
        return appConfigRepository.getOne(id);
    }

    @Override
    public List<AppConfig> query(Map<String, String> kv) {
        Specification<AppConfig> specification = (root, query, cb) -> {
            List<Predicate> predicates = new ArrayList<>();
            kv.forEach((name, value) -> {
                predicates.add(cb.like(root.get(name), "%" + value + "%"));
            });

            // select * from app_building where app_id like '%test%' and app_name like '%测试%'
            return cb.and(predicates.toArray(new Predicate[0]));
        };
        return appConfigRepository.findAll(specification);
    }

    @Override
    public AppConfig findByRepoAndBranch(String repo, String branch) {
        List<AppConfig> list = appConfigRepository.findByAppRepoAndRepoBranch(repo, branch);
        return list.size() == 1 ? list.get(0) : null;
    }

    //@Cacheable({"appId"})
    @Override
    public AppConfig findByAppId(String appId) {
        return appConfigRepository.findByDeletedFalseAndAppId(appId);
    }

    @Override
    public Page<AppConfigVO> findByEnvAndType(String env, String type, Pageable pageable) {
        Page<AppConfig> page = appConfigRepository.findByEnvAndAppType(env, type, pageable);
        List<AppConfigVO> list = page.stream()
                .map(appConfig -> {
                    int total = deployConfigRepository.countByAppConfig(appConfig);
                    return new AppConfigVO(appConfig, total);
                })
                .collect(Collectors.toList());
        return new PageImpl<>(list, page.getPageable(), page.getTotalElements());
    }

    //@Cacheable({"appId"})
    @Override
    public List<AppConfig> findAll() {
        return appConfigRepository.findAll();
    }

    @Override
    public List<AppConfig> findAllByRepoAuthConfig(RepoAuthConfig repoAuthConfig) {
        return appConfigRepository.findAllByRepoAuthConfig(repoAuthConfig);
    }

    @Override
    public List<AppConfig> findAllByCompilerConfig(CompilerConfig compilerConfig) {
        return appConfigRepository.findAllByCompilerConfig(compilerConfig);
    }

    @Override
    public List<AppConfig> findAllByPackerConfig(PackerConfig packerConfig) {
        return appConfigRepository.findAllByPackerConfig(packerConfig);
    }

    @Override
    public Page<AppBuildingVO> getByPage(String appEnv, String appType, PageRequest pageRequest) {
        Page<AppBuilding> page = buildingRepository.findAllByAppConfig_EnvAndAppConfig_AppType(appEnv, appType, pageRequest);
        List<AppBuildingVO> list = page.getContent().stream().map(AppBuildingVO::new).collect(Collectors.toList());
        return new PageImpl<>(list, pageRequest, page.getTotalElements());
    }

    @Override
    public Page<AppBuildingVO> getPageByName(String appName, PageRequest pageRequest) {
        Page<AppBuilding> page = buildingRepository.findAllByAppConfig_AppName(appName, pageRequest);
        List<AppBuildingVO> list = page.getContent().stream().map(AppBuildingVO::new).collect(Collectors.toList());
        return new PageImpl<>(list, pageRequest, page.getTotalElements());
    }

    @Override
    public AppConfig getAppConfig(String appId) {
        AppBuilding appBuilding1 = buildingRepository.findAllByAppConfig_AppId(appId);
        return appBuilding1.getAppConfig();
    }

    @Override
    public boolean isBuilding(String appId) {
        AppBuilding appBuilding1 = buildingRepository.findAllByAppConfig_AppId(appId);
        if (appBuilding1 == null) {
            return false;
        }

        return appBuilding1.isOnBuilding();
    }

    @Deprecated
    public AppBuilding getAppBuilding(String appId) {
        AppBuilding appBuilding1 = buildingRepository.findAllByAppConfig_AppId(appId);
        return appBuilding1;
    }

    @Override
    public Page<BuildLogVO> buildLogVOs(String appId, PageRequest pageRequest) {
        AppConfig appConfig = appConfigRepository.findByAppId(appId);
        return buildLogRepository.findByAppConfig(appConfig, pageRequest).map(BuildLogVO::new);
    }

    @Override
    public BuildLog findByBuildLogId(String buildLogId) {
        return buildLogRepository.findByBuildLogId(buildLogId);
    }

    @Override
    public String getBuildResult(String buildLogId) {
        BuildLog buildLog = buildLogRepository.findByBuildLogId(buildLogId);
        if (buildLog != null) {
            return buildLog.getMsg();
        }
        return "";
    }
}
