package cn.reghao.devops.web.mgr.app.service.bd.impl;

import cn.reghao.devops.common.docker.po.DockerAuth;
import cn.reghao.devops.common.msg.constant.PackType;
import cn.reghao.devops.web.mgr.app.db.query.AppDeployQuery;
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.builds.model.po.DockerRegistry;
import cn.reghao.devops.web.mgr.app.model.po.config.AppConfig;
import cn.reghao.devops.web.mgr.app.model.po.config.AppDeployConfig;
import cn.reghao.devops.web.mgr.app.model.po.log.BuildLog;
import cn.reghao.devops.web.mgr.app.service.bd.DeployApp;
import cn.reghao.devops.web.mgr.app.service.AppDeployService;
import cn.reghao.devops.web.mgr.machine.db.query.MachineQuery;
import cn.reghao.devops.common.msg.event.EvtAppDeploy;
import cn.reghao.devops.common.msg.event.EvtAppStatResult;
import cn.reghao.devops.web.ws.WsSender;
import cn.reghao.jutil.jdk.event.message.EventMessage;
import cn.reghao.jutil.jdk.result.Result;
import cn.reghao.jutil.jdk.result.ResultStatus;
import lombok.extern.slf4j.Slf4j;
import org.springframework.data.domain.PageRequest;
import org.springframework.stereotype.Service;

import java.io.IOException;

/**
 * @author reghao
 * @date 2023-02-28 11:40:45
 */
@Slf4j
@Service
public class DeployAppImpl implements DeployApp {
    private final MachineQuery machineQuery;
    private final WsSender wsSender;
    private AppDeployQuery appDeployQuery;
    private final AppDeployService appDeployService;
    private final BuildLogRepository buildLogRepository;

    public DeployAppImpl(MachineQuery machineQuery, WsSender wsSender, AppDeployQuery appDeployQuery,
                         AppDeployService appDeployService, BuildLogRepository buildLogRepository) {
        this.wsSender = wsSender;
        this.appDeployQuery = appDeployQuery;
        this.appDeployService = appDeployService;
        this.buildLogRepository = buildLogRepository;
        this.machineQuery = machineQuery;
    }

    @Override
    public void deploy(String buildLogId) {
        BuildLog buildLog = buildLogRepository.findByBuildLogId(buildLogId);
        AppBuilding appBuilding = new AppBuilding(buildLog);
        deploy(appBuilding);
    }

    @Override
    public void deploy(String buildLogId, String machineId) {
        BuildLog buildLog = buildLogRepository.findByBuildLogId(buildLogId);
        AppBuilding appBuilding = new AppBuilding(buildLog);
        String appId = appBuilding.getAppConfig().getAppId();
        AppDeployConfig appDeployConfig = appDeployQuery.findByAppIdAndMachineId(appId, machineId);
        deploy(appBuilding, appDeployConfig);
    }

    @Override
    public void deploy(AppBuilding appBuilding) {
        AppConfig appConfig = appBuilding.getAppConfig();
        PageRequest pageRequest = PageRequest.of(0, 10);
        appDeployQuery.findByAppId(appConfig.getAppId(), pageRequest)
                .forEach(appDeployConfig -> deploy(appBuilding, appDeployConfig));
    }

    private void deploy(AppBuilding appBuilding, AppDeployConfig appDeployConfig) {
        String deployBy = appBuilding.getBuildBy();
        String packagePath = appBuilding.getPackagePath();

        String appId = appDeployConfig.getAppConfig().getAppId();
        String packType = appDeployConfig.getAppConfig().getPackerConfig().getType();

        String machineId = appDeployConfig.getMachineHost().getMachineId();
        String startScript = appDeployConfig.getStartScript();
        String startHome = appDeployConfig.getStartHome();
        String unpackScript = appDeployConfig.getUnpackScript();

        EvtAppDeploy deployParam = new EvtAppDeploy();
        deployParam.setAppId(appId);
        deployParam.setPackagePath(packagePath);
        deployParam.setPackType(packType);
        deployParam.setStartScript(startScript);
        deployParam.setStartHome(startHome);
        if (packType.equals(PackType.docker.getName())) {
            DockerRegistry registry = appDeployConfig.getAppConfig().getPackerConfig().getDockerRegistry();
            if (registry != null) {
                DockerAuth dockerAuth = new DockerAuth(registry.getRegistryUrl(), registry.getUsername(), registry.getPassword());
                deployParam.setDockerAuth(dockerAuth);
            }
        }

        if (appDeployQuery.isDeploying(appId, machineId)) {
            log.info("应用正在部署...");
            return;
        }

        if (!machineQuery.isAgentOnline(machineId)) {
            return;
        }

        appDeployService.beforeDeploy(appBuilding, machineId, deployBy);
        EventMessage evtMsg = EventMessage.evt(deployParam);
        try {
            wsSender.send(machineId, evtMsg);
        } catch (IOException e) {
            e.printStackTrace();
            EvtAppStatResult statResult = new EvtAppStatResult(appId, machineId);
            statResult.setResult(Result.result(ResultStatus.FAIL, "连接异常"));
            appDeployService.afterDeploy(statResult);
        }
    }
}
