package core

import (
	"context"
	clientCore "gitlink.org.cn/JointCloud/pcm-coordinator/api/client"
	"gitlink.org.cn/JointCloud/pcm-coordinator/pkg/constants"
	"gitlink.org.cn/JointCloud/pcm-coordinator/pkg/models"
	"gorm.io/gorm"
	"strings"

	"github.com/zeromicro/go-zero/core/logx"
	"gitlink.org.cn/JointCloud/pcm-coordinator/api/internal/svc"
)

type PushTaskInfoLogic struct {
	logx.Logger
	ctx    context.Context
	svcCtx *svc.ServiceContext
}

func NewPushTaskInfoLogic(ctx context.Context, svcCtx *svc.ServiceContext) *PushTaskInfoLogic {
	return &PushTaskInfoLogic{
		Logger: logx.WithContext(ctx),
		ctx:    ctx,
		svcCtx: svcCtx,
	}
}

func (l *PushTaskInfoLogic) PushTaskInfo(req *clientCore.PushTaskInfoReq) (*clientCore.PushTaskInfoResp, error) {
	resp := clientCore.PushTaskInfoResp{}
	var kind int32
	l.svcCtx.DbEngin.Raw("select type as kind from t_adapter where id = ?", req.AdapterId).Scan(&kind)
	switch kind {
	case 0:
		for _, cloudInfo := range req.CloudInfoList {
			l.svcCtx.DbEngin.Exec("update cloud set status = ?,start_time = ?,result = ? where participant_id = ? and id = ?",
				cloudInfo.Status, cloudInfo.StartTime, cloudInfo.Result, req.AdapterId, cloudInfo.Id)
			syncTask(l.svcCtx.DbEngin, cloudInfo.TaskId)
		}
	case 2:
		for _, hpcInfo := range req.HpcInfoList {
			l.svcCtx.DbEngin.Exec("update task_hpc set status = ?,start_time = ?,job_id = ? where cluster_id = ? and task_id = ? and name = ?",
				hpcInfo.Status, hpcInfo.StartTime, hpcInfo.JobId, hpcInfo.ClusterId, hpcInfo.TaskId, hpcInfo.Name)
			syncTask(l.svcCtx.DbEngin, hpcInfo.TaskId)
		}
	case 1:
		for _, aiInfo := range req.AiInfoList {
			l.svcCtx.DbEngin.Exec("update ai set status = ?,start_time = ?,project_id = ?,job_id = ? where participant_id = ? and task_id = ? and name = ?",
				aiInfo.Status, aiInfo.StartTime, aiInfo.ProjectId, aiInfo.JobId, req.AdapterId, aiInfo.TaskId, aiInfo.Name)
			syncTask(l.svcCtx.DbEngin, aiInfo.TaskId)
		}
	case 3:
		for _, vmInfo := range req.VmInfoList {
			l.svcCtx.DbEngin.Exec("update task_vm set status = ?,start_time = ?  where participant_id = ? and task_id = ? and name = ?",
				vmInfo.Status, vmInfo.StartTime, req.AdapterId, vmInfo.TaskId, vmInfo.Name)
			syncTask(l.svcCtx.DbEngin, vmInfo.TaskId)
		}
	}

	return &resp, nil
}

func syncTask(gorm *gorm.DB, taskId int64) {

	var allStatus string
	tx := gorm.Raw("SELECT CONCAT_WS(',',GROUP_CONCAT(DISTINCT h.status) ,GROUP_CONCAT(DISTINCT  a.status) ,GROUP_CONCAT(DISTINCT c.status))as status from task t left join hpc h on t.id  = h.task_id left join cloud c  on t.id  = c.task_id left join ai a on t.id  = a.task_id where t.id  = ?", taskId).Scan(&allStatus)
	if tx.Error != nil {
		logx.Error(tx.Error)
	}
	// 子状态统一则修改主任务状态
	statusArray := strings.Split(allStatus, ",")
	if len(removeRepeatedElement(statusArray)) == 1 {
		updateTask(gorm, taskId, statusArray[0])

	}
	// 子任务包含失败状态 主任务则失败
	if strings.Contains(allStatus, constants.Failed) {
		updateTask(gorm, taskId, constants.Failed)

	}
	if strings.Contains(allStatus, constants.Running) {
		updateTask(gorm, taskId, constants.Running)
	}

}

func updateTask(gorm *gorm.DB, taskId int64, status string) {
	var task models.Task
	gorm.Where("id = ? ", taskId).Find(&task)
	if task.Status != status {
		task.Status = status
		gorm.Updates(&task)
	}
}

func removeRepeatedElement(arr []string) (newArr []string) {
	newArr = make([]string, 0)
	for i := 0; i < len(arr); i++ {
		repeat := false
		for j := i + 1; j < len(arr); j++ {
			if arr[i] == arr[j] {
				repeat = true
				break
			}
		}
		if !repeat {
			newArr = append(newArr, arr[i])
		}
	}
	return
}
