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

import cn.reghao.bnt.common.msg.constant.NodeStatus;
import cn.reghao.bnt.common.msg.event.EvtAgentHeartbeat;
import cn.reghao.bnt.common.msg.event.EvtAgentStart;
import cn.reghao.bnt.web.devops.util.DefaultSetting;
import cn.reghao.bnt.web.devops.machine.db.repository.MachineHostRepository;
import cn.reghao.bnt.web.devops.machine.db.repository.MachineInfoRepository;
import cn.reghao.bnt.web.devops.machine.model.po.MachineHost;
import cn.reghao.bnt.web.devops.machine.model.po.MachineInfo;
import cn.reghao.bnt.web.devops.machine.service.MachineQuery;
import cn.reghao.bnt.web.devops.machine.service.MachineService;
import cn.reghao.jutil.jdk.web.result.Result;
import cn.reghao.jutil.jdk.web.result.ResultStatus;
import lombok.extern.slf4j.Slf4j;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;

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

/**
 * @author reghao
 * @date 2019-11-15 08:48:04
 */
@Slf4j
@Service
public class MachineServiceImpl implements MachineService {
    private final DefaultSetting defaultSetting;
    private final MachineHostRepository machineHostRepository;
    private final MachineInfoRepository machineInfoRepository;
    private final MachineQuery machineQuery;

    public MachineServiceImpl(DefaultSetting defaultSetting, MachineHostRepository machineHostRepository,
                              MachineInfoRepository machineInfoRepository, MachineQuery machineQuery) {
        this.defaultSetting = defaultSetting;
        this.machineHostRepository = machineHostRepository;
        this.machineInfoRepository = machineInfoRepository;
        this.machineQuery = machineQuery;
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void addOrUpdateMachine(EvtAgentStart evtAgentStart) {
        String machineId = evtAgentStart.getMachineId();
        long timestamp = evtAgentStart.getTimestamp();
        List<MachineInfo> machineInfoList = machineQuery.getMachineInfos(List.of(machineId));
        if (machineInfoList.isEmpty()) {
            MachineInfo machineInfo = new MachineInfo(evtAgentStart);
            machineInfo = machineInfoRepository.save(machineInfo);
            String env = defaultSetting.getDefaultEnv();
            machineHostRepository.save(new MachineHost(machineInfo, env));
        } else {
            machineInfoRepository.updateMachineStat(machineId, NodeStatus.Online.getCode());
        }
    }

    @Override
    public void updateMachine(EvtAgentHeartbeat evtAgentHeartbeat) {
        // TODO 根据 EvtAgentHeartbeat 中的信息检查系统负载，CPU，内存，磁盘等使用情况(暂未实现)
    }

    @Override
    public void setMachineEnv(String machineId, String env) {
        MachineHost machineHost = machineQuery.getMachineHost(machineId);
        machineHost.setEnv(env);
        machineHostRepository.save(machineHost);
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void setMachineDeprecate(String machineId) {
        List<MachineInfo> list = machineQuery.getMachineInfos(List.of(machineId));
        if (!list.isEmpty() && Objects.equals(list.get(0).getStat(), NodeStatus.Offline.getCode())) {
            machineInfoRepository.updateMachineStat(machineId, NodeStatus.Deprecated.getCode());
        }
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void setAgentStatus(String machineId, NodeStatus nodeStatus) {
        machineInfoRepository.updateMachineStat(machineId, nodeStatus.getCode());
    }

    @Transactional(rollbackFor = Exception.class)
    @Override
    public void setMachineOffline() {
        List<MachineInfo> list = machineInfoRepository.findByStat(NodeStatus.Online.getCode()).stream()
                .filter(machineInfo -> !machineInfo.getMachineId().startsWith("oss"))
                .collect(Collectors.toList());

        list.forEach(machineInfo -> {
            String machineId = machineInfo.getMachineId();
            machineInfoRepository.updateMachineStat(machineId, NodeStatus.Offline.getCode());
        });
    }

    @Transactional(rollbackFor = Exception.class)
    public Result deleteMachine(String machineId) {
        MachineHost machineHost = machineQuery.getMachineHost(machineId);
        if (machineHost == null) {
            return Result.result(ResultStatus.FAIL, "节点不存在");
        }

        MachineInfo machineInfo = machineHost.getMachineInfo();
        if (!machineInfo.getStat().equals(NodeStatus.Deprecated.getCode())) {
            return Result.result(ResultStatus.FAIL, "只能删除 Deprecated 状态的节点");
        }

        machineHostRepository.deleteByMachineId(machineId);
        machineInfoRepository.deleteByMachineId(machineId);
        return Result.result(ResultStatus.SUCCESS);
    }
}
