/*

 Copyright (c) [2023] [pcm]
 [pcm-coordinator] is licensed under Mulan PSL v2.
 You can use this software according to the terms and conditions of the Mulan PSL v2.
 You may obtain a copy of Mulan PSL v2 at:
          http://license.coscl.org.cn/MulanPSL2
 THIS SOFTWARE IS PROVIDED ON AN "AS IS" BASIS, WITHOUT WARRANTIES OF ANY KIND,
 EITHER EXPaRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO NON-INFRINGEMENT,
 MERCHANTABILITY OR FIT FOR A PARTICULAR PURPOSE.
 See the Mulan PSL v2 for more details.

*/

package pcmcorelogic

import (
	"context"
	"gitlink.org.cn/JointCloud/pcm-coordinator/pkg/constants"
	"gitlink.org.cn/JointCloud/pcm-coordinator/pkg/models"
	"gitlink.org.cn/JointCloud/pcm-coordinator/rpc/internal/svc"
	"gitlink.org.cn/JointCloud/pcm-coordinator/rpc/pcmCore"
	"gorm.io/gorm"
	"strings"
	"time"

	"github.com/zeromicro/go-zero/core/logx"
)

type ExternalInfo struct {
	TaskId        int64
	ExternalField string
	Name          string
	Status        string
	StartTime     time.Time
	RunningTime   int64
}
type SyncInfoLogic struct {
	ctx    context.Context
	svcCtx *svc.ServiceContext
	logx.Logger
}

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

// SyncInfo Synchronous data information
func (l *SyncInfoLogic) SyncInfo(in *pcmCore.SyncInfoReq) (*pcmCore.SyncInfoResp, error) {
	// 查询p端类型
	var kind string
	l.svcCtx.DbEngin.Raw("select type as kind from sc_participant_phy_info where id = ?", in.ParticipantId).Scan(&kind)
	switch kind {
	case constants.CLOUD, constants.SEALOS:
		for _, cloudInfo := range in.CloudInfoList {
			l.svcCtx.DbEngin.Exec("update cloud set status = ?,start_time = ?,result = ? where participant_id = ? and id = ?",
				cloudInfo.Status, cloudInfo.StartTime, cloudInfo.Result, in.ParticipantId, cloudInfo.Id)
			syncTask(l.svcCtx.DbEngin, cloudInfo.TaskId)
		}
	case constants.HPC:
		for _, hpcInfo := range in.HpcInfoList {
			l.svcCtx.DbEngin.Exec("update hpc set status = ?,start_time = ?,job_id = ? where participant_id = ? and task_id = ? and name = ?",
				hpcInfo.Status, hpcInfo.StartTime, hpcInfo.RunningTime, hpcInfo.JobId, in.ParticipantId, hpcInfo.TaskId, hpcInfo.Name)
			syncTask(l.svcCtx.DbEngin, hpcInfo.TaskId)
		}
	case constants.AI:
		for _, aiInfo := range in.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, in.ParticipantId, aiInfo.TaskId, aiInfo.Name)
			syncTask(l.svcCtx.DbEngin, aiInfo.TaskId)
		}
	}

	return &pcmCore.SyncInfoResp{}, 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
}
