package com.ruoyi.platform.service.impl;

import com.ruoyi.common.redis.service.RedisService;
import com.ruoyi.common.security.utils.SecurityUtils;
import com.ruoyi.system.api.constant.Constant;
import com.ruoyi.platform.domain.DevEnvironment;
import com.ruoyi.platform.domain.PodStatus;
import com.ruoyi.platform.mapper.DevEnvironmentDao;
import com.ruoyi.platform.service.DevEnvironmentService;
import com.ruoyi.platform.service.JupyterService;
import com.ruoyi.platform.service.ResourceOccupyService;
import com.ruoyi.platform.utils.JacksonUtil;
import com.ruoyi.platform.utils.K8sClientUtil;
import com.ruoyi.platform.utils.MinioUtil;
import com.ruoyi.platform.utils.MlflowUtil;
import com.ruoyi.platform.vo.PodStatusVo;
import com.ruoyi.system.api.model.LoginUser;
import io.kubernetes.client.openapi.models.V1PersistentVolumeClaim;
import io.kubernetes.client.openapi.models.V1Pod;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.Lazy;
import org.springframework.stereotype.Service;

import javax.annotation.Resource;
import java.io.InputStream;
import java.util.List;
import java.util.Map;

@Service
public class JupyterServiceImpl implements JupyterService {

    @Value("${jupyter.image}")
    private String image;
    @Value("${jupyter.port}")
    private Integer port;
    @Value("${jupyter.namespace}")
    private String namespace;
    @Value("${jupyter.mountPath}")
    private String mountPath;
    @Value("${jupyter.storage}")
    private String storage;
    @Value("${jupyter.masterIp}")
    private String masterIp;
    @Value("${k8s.storageClassName}")
    private String storageClassName;
    @Value("${minio.platformPvcName}")
    private String minioPvcName;

    private final MinioUtil minioUtil;

    @Resource
    private K8sClientUtil k8sClientUtil;
    @Resource
    private MlflowUtil mlflowUtil;

    @Resource
    private DevEnvironmentDao devEnvironmentDao;

    @Resource
    @Lazy
    private DevEnvironmentService devEnvironmentService;

    @Resource
    private RedisService redisService;

    @Resource
    private ResourceOccupyService resourceOccupyService;

    public JupyterServiceImpl(MinioUtil minioUtil) {
        this.minioUtil = minioUtil;
    }

    @Override
    public String getJupyterServiceUrl() {
        LoginUser loginUser = SecurityUtils.getLoginUser();
        String podName = loginUser.getUsername().toLowerCase() + "-editor-pod";
        String pvcName = loginUser.getUsername().toLowerCase() + "-editor-pvc";
        V1PersistentVolumeClaim pvc = k8sClientUtil.createPvc(namespace, pvcName, storage, storageClassName);
        Integer podPort = k8sClientUtil.createPod(podName, namespace, port, mountPath, pvc, image);
        return masterIp + ":" + podPort;

    }

    @Override
    public String runJupyterService(Integer id) throws Exception {
        DevEnvironment devEnvironment = this.devEnvironmentDao.queryById(id);
        if (devEnvironment == null) {
            throw new Exception("开发环境配置不存在");
        }

        // 提取数据集,模型信息，得到数据集模型的path
        Map<String, Object> dataset = JacksonUtil.parseJSONStr2Map(devEnvironment.getDataset());
//        String datasetPath = "argo-workflow" + "/" + dataset.get("path");
        String datasetPath = (String) dataset.get("path");

        Map<String, Object> model = JacksonUtil.parseJSONStr2Map(devEnvironment.getModel());
//        String modelPath = "argo-workflow" + "/" + model.get("path");
        String modelPath = (String) model.get("path");

        //构造pod名称
        String podName = devEnvironment.getCreateBy() + "-editor-pod" + "-" + id;
        //新建编辑器的pvc
//        String pvcName = loginUser.getUsername().toLowerCase() + "-editor-pvc";
//        V1PersistentVolumeClaim pvc = k8sClientUtil.createPvc(namespace, pvcName, storage, storageClassName);

        // 调用修改后的 createPod 方法，传入额外的参数
//        Integer podPort = k8sClientUtil.createConfiguredPod(podName, namespace, port, mountPath, pvc, devEnvironment, minioPvcName, datasetPath, modelPath);
        Integer podPort = k8sClientUtil.createConfiguredPod(podName, namespace, port, mountPath, null, devEnvironment, minioPvcName, datasetPath, modelPath);
        String url = masterIp + ":" + podPort;
        redisService.setCacheObject(podName, masterIp + ":" + podPort);
        devEnvironment.setStatus(Constant.Pending);
        devEnvironment.setUrl(url);
        this.devEnvironmentService.update(devEnvironment);
        return url;

    }


    @Override
    public String stopJupyterService(Integer id) throws Exception {
        DevEnvironment devEnvironment = this.devEnvironmentDao.queryById(id);
        if (devEnvironment == null) {
            throw new Exception("开发环境配置不存在");
        }
        //构造pod和svc名称
        String podName = devEnvironment.getCreateBy() + "-editor-pod" + "-" + id;
        String svcName = devEnvironment.getCreateBy() + "-editor-pod" + "-" + id + "-svc";
        //得到pod
        V1Pod pod = k8sClientUtil.getNSPodList(namespace, podName);
        if (pod == null) {
            return "pod不存在！";
        }

        // 使用 Kubernetes API 删除 Pod
        String deleteResult = k8sClientUtil.deletePod(podName, namespace);
        // 删除service
        k8sClientUtil.deleteService(svcName, namespace);

        devEnvironment.setStatus(Constant.Terminated);
        this.devEnvironmentService.update(devEnvironment);

        // 结束扣积分
        resourceOccupyService.endDeduce(Constant.TaskType_Dev, Long.valueOf(id), null, null, null);
        return deleteResult + "，编辑器已停止";

    }

    @Override
    public PodStatusVo getJupyterStatus(DevEnvironment devEnvironment) throws Exception {
        String status = PodStatus.Terminated.getName();
        PodStatusVo JupyterStatusVo = new PodStatusVo();
        JupyterStatusVo.setStatus(status);
        if (devEnvironment == null) {
            return JupyterStatusVo;
        }
        String podName = devEnvironment.getCreateBy() + "-editor-pod" + "-" + devEnvironment.getId();

        try {
            // 查询相应pod状态
            String podStatus = k8sClientUtil.getPodStatus(podName, namespace);
            for (PodStatus s : PodStatus.values()) {
                if (s.getName().equals(podStatus)) {
                    status = s.getName();
                    break;
                }
            }

        } catch (Exception e) {
            return JupyterStatusVo;
        }
        String url = redisService.getCacheObject(podName);
        JupyterStatusVo.setStatus(status);
        JupyterStatusVo.setUrl(url);
        return JupyterStatusVo;

    }


    @Override
    public void upload(InputStream inputStream) {
        try {
            minioUtil.uploadObject("platform-data", "/pytorch/testupload4008208820", inputStream);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

    @Override
    public void mlflow() {
        List<org.mlflow.api.proto.Service.Experiment> experiments = mlflowUtil.getExperiments();
        List<org.mlflow.api.proto.Service.RunInfo> runs = mlflowUtil.getRuns(experiments.get(1).getExperimentId());
        org.mlflow.api.proto.Service.Run data = mlflowUtil.getData(runs.get(0).getRunId());
        System.out.println(experiments);
    }


}
