package status

import (
	jsoniter "github.com/json-iterator/go"
	"github.com/rs/zerolog/log"
	"github.com/zeromicro/go-zero/core/logx"
	"gitlink.org.cn/JointCloud/pcm-coordinator/internal/scheduler/service/utils/jcs"
	"gitlink.org.cn/JointCloud/pcm-coordinator/internal/svc"
	"gitlink.org.cn/JointCloud/pcm-coordinator/internal/types"
	"gitlink.org.cn/JointCloud/pcm-coordinator/pkg/constants"
	"gitlink.org.cn/JointCloud/pcm-coordinator/pkg/models"
	"gitlink.org.cn/JointCloud/pcm-coordinator/pkg/utils"
	"net/http"
	"strconv"
)

func reportHpcStatusMessages(svc *svc.ServiceContext, task *types.TaskModel, hpcTask *models.TaskHpc, status bool, message string) error {
	report := &jcs.JobStatusReportReq{}
	reportMsg := &jcs.TrainReportMessage{
		Type:      "Train",
		TaskName:  task.Name,
		TaskID:    strconv.FormatInt(task.Id, 10),
		Status:    status,
		Message:   message,
		ClusterID: strconv.FormatInt(hpcTask.ClusterId, 10),
		Output:    hpcTask.WorkDir,
	}
	report.Report = reportMsg

	marshal, _ := jsoniter.MarshalToString(report)
	log.Debug().Msgf("通知中间件任务状态参数: [%v]", marshal)
	err := jcs.StatusReport(svc.Scheduler.AiService.Conf.JcsMiddleware.JobStatusReportUrl, report)
	if err != nil {
		logx.Errorf("############ Report Status Message Error %s", err.Error())
		return err
	}
	return nil
}

// UpdateHpcTaskStatus 更新超算任务状态，并通知中间件
func UpdateHpcTaskStatus(svc *svc.ServiceContext) {
	svc.Scheduler.HpcService.TaskSyncLock.Lock()
	defer svc.Scheduler.HpcService.TaskSyncLock.Unlock()
	taskList := make([]*models.TaskHpc, 0)
	sqlStr := `SELECT *
				FROM task_hpc
				WHERE
					job_id != ''
					AND (
						status NOT IN ('Failed', 'Completed', 'Cancelled')
						OR start_time < created_time
					)
				ORDER BY created_time DESC
				LIMIT 10`
	db := svc.DbEngin.Raw(sqlStr).Scan(&taskList)
	if db.Error != nil {
		logx.Errorf(db.Error.Error())
		return
	}
	for _, hpc := range taskList {
		//更新task表的超算任务状态
		task := &types.TaskModel{}
		tx := svc.DbEngin.Model(models.Task{}).Where("id", hpc.TaskId).Scan(&task)
		if tx.Error != nil {
			logx.Errorf(tx.Error.Error())
			break
		}
		clusterId := utils.Int64ToString(hpc.ClusterId)
		h := http.Request{}
		hpcTask, err := svc.Scheduler.HpcService.HpcExecutorAdapterMap[strconv.FormatInt(hpc.AdapterId, 10)].GetTask(h.Context(), hpc.JobId, clusterId)
		if err != nil {
			logx.Errorf(err.Error())
			break
		}
		switch hpcTask.Status {
		case constants.Running:
			if hpc.Status != hpcTask.Status {
				svc.Scheduler.HpcStorages.AddNoticeInfo(strconv.FormatInt(hpc.AdapterId, 10), hpc.AdapterName, strconv.FormatInt(hpc.ClusterId, 10), hpc.ClusterName, hpc.Name, "running", "任务运行中")
				hpc.Status = hpcTask.Status
				task.Status = hpcTask.Status
			}
		case constants.Failed:
			if hpc.Status != hpcTask.Status {
				svc.Scheduler.HpcStorages.AddNoticeInfo(strconv.FormatInt(hpc.AdapterId, 10), hpc.AdapterName, strconv.FormatInt(hpc.ClusterId, 10), hpc.ClusterName, hpc.Name, "failed", "任务失败")
				hpc.Status = hpcTask.Status
				task.Status = hpcTask.Status
				logx.Infof("[%v]：任务执行失败，发送通知, 任务状态: [%v]", hpcTask, hpcTask.Status)
				_ = reportHpcStatusMessages(svc, task, hpc, false, "任务失败")
			}
		case constants.Completed:
			if hpc.Status != hpcTask.Status {
				svc.Scheduler.HpcStorages.AddNoticeInfo(strconv.FormatInt(hpc.AdapterId, 10), hpc.AdapterName, strconv.FormatInt(hpc.ClusterId, 10), hpc.ClusterName, hpc.Name, "completed", "任务完成")
				hpc.Status = hpcTask.Status
				task.Status = hpcTask.Status
				logx.Infof("[%v]：任务执行完成，发送通知, 任务状态: [%v]", hpcTask, hpcTask.Status)
				_ = reportHpcStatusMessages(svc, task, hpc, true, "任务完成")
			}
		default:
			if hpc.Status != hpcTask.Status {
				svc.Scheduler.HpcStorages.AddNoticeInfo(strconv.FormatInt(hpc.AdapterId, 10), hpc.AdapterName, strconv.FormatInt(hpc.ClusterId, 10), hpc.ClusterName, hpc.Name, "pending", "任务pending")
				hpc.Status = hpcTask.Status
				task.Status = hpcTask.Status
			}
		}
		task.StartTime = hpcTask.Start
		task.EndTime = hpcTask.End
		hpc.StartTime = hpcTask.Start
		hpc.EndTime = hpcTask.End
		logx.Info("# task 开始时间: %v, 结束时间: %v", task.StartTime, task.EndTime)
		err = svc.Scheduler.HpcStorages.UpdateTask(task)
		if err != nil {
			logx.Errorf(err.Error())
			break
		}
		err = svc.Scheduler.HpcStorages.UpdateHpcTask(hpc)
		if err != nil {
			logx.Errorf(err.Error())
			break
		}
	}
}
