package cn.reghao.bnt.web.devops.build.service.impl;

import cn.reghao.bnt.web.devops.app.db.query.AppBuildQuery;
import cn.reghao.bnt.web.devops.app.model.po.config.AppConfig;
import cn.reghao.bnt.web.devops.build.db.repository.CompilerConfigRepository;
import cn.reghao.bnt.web.devops.build.model.po.CompilerConfig;
import cn.reghao.bnt.web.devops.build.service.CompilerConfigService;
import cn.reghao.bnt.web.devops.builder.chain.BuildTools;
import cn.reghao.bnt.web.devops.builder.model.constant.CompileType;
import cn.reghao.bnt.web.util.StringUtil;
import cn.reghao.jutil.jdk.web.result.Result;
import cn.reghao.jutil.jdk.web.result.ResultStatus;
import cn.reghao.jutil.jdk.shell.ShellExecutor;
import cn.reghao.jutil.jdk.shell.ShellResult;
import org.springframework.stereotype.Service;

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

/**
 * @author reghao
 * @date 2021-09-17 15:54:07
 */
@Service
public class CompilerConfigServiceImpl implements CompilerConfigService {
    private final CompilerConfigRepository compilerConfigRepository;
    private final AppBuildQuery appBuildQuery;
    private final ShellExecutor shellExecutor;

    public CompilerConfigServiceImpl(CompilerConfigRepository compilerConfigRepository, AppBuildQuery appBuildQuery,
                                     ShellExecutor shellExecutor) {
        this.compilerConfigRepository = compilerConfigRepository;
        this.appBuildQuery = appBuildQuery;
        this.shellExecutor = shellExecutor;
    }

    @Override
    public Result addOrUpdate(CompilerConfig compilerConfig) {
        String name = compilerConfig.getName();
        CompilerConfig entity = compilerConfigRepository.findByName(name);
        if (entity == null) {
            String type = compilerConfig.getType();
            if (type.equals(CompileType.docker.getName())) {
                // TODO pull 编译器镜像, 验证是否可用
                String compilerImage = compilerConfig.getCompilerImage();
            }

            compilerConfigRepository.save(compilerConfig);
            return Result.result(ResultStatus.SUCCESS);
        }

        String compileCmd = compilerConfig.getCompileCmd();
        String versionCmd = compilerConfig.getVersionCmd();
        entity.setCompileCmd(compileCmd);
        entity.setVersionCmd(versionCmd);
        Result result = checkBeforeUpdate(compilerConfig);
        if (result.getCode() == ResultStatus.SUCCESS.getCode()) {
            compilerConfigRepository.save(entity);
        }

        return result;
    }

    private Result checkBeforeUpdate(CompilerConfig compilerConfig) {
        BuildTools.removeCodeCompiler(compilerConfig.getName());
        return Result.result(ResultStatus.SUCCESS);
    }

    @Override
    public Result delete(int id) {
        CompilerConfig compilerConfig = compilerConfigRepository.findById(id).orElse(null);
        if (compilerConfig != null) {
            BuildTools.removeCodeCompiler(compilerConfig.getName());
            compilerConfigRepository.deleteById(id);
        }

        return Result.result(ResultStatus.SUCCESS);
    }

    private Result checkBeforeDelete(CompilerConfig compilerConfig) {
        List<AppConfig> apps = appBuildQuery.findAllByCompilerConfig(compilerConfig);
        if (!apps.isEmpty()) {
            List<String> ids = apps.stream().map(AppConfig::getAppId).collect(Collectors.toList());
            String msg = compilerConfig.getName() + " 删除失败, " + ids.toString() + " 等应用正在使用";
            return Result.result(ResultStatus.FAIL, msg);
        }

        BuildTools.removeCodeCompiler(compilerConfig.getName());
        return Result.result(ResultStatus.SUCCESS);
    }

    @Override
    public String getCompilerVersion(int id) {
        CompilerConfig compilerConfig = compilerConfigRepository.findById(id).orElse(null);
        if (compilerConfig == null) {
            return "not exist";
        }

        if (!compilerConfig.getType().equals(CompileType.shell.getName())) {
            return "not shell type";
        }

        String versionCmd = compilerConfig.getVersionCmd();
        ShellResult shellResult = shellExecutor.exec(versionCmd.split("\\s+"));
        String html = StringUtil.txtToHtml(shellResult.getResult());
        return html;
    }
}
