package core

import (
	"context"
	"fmt"
	clientCore "gitlink.org.cn/JointCloud/pcm-coordinator/client"
	"gitlink.org.cn/JointCloud/pcm-coordinator/internal/scheduler/schedulers"
	"gitlink.org.cn/JointCloud/pcm-coordinator/internal/scheduler/schedulers/option"
	"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"
	"strconv"
	"time"

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

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

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

func (l *CommitVmTaskLogic) CommitVmTask(req *types.CommitVmTaskReq) (resp *types.CommitVmTaskResp, err error) {
	// todo: add your logic here and delete this line
	resp = &types.CommitVmTaskResp{}
	tx := l.svcCtx.DbEngin.Begin()
	var adaptersName string
	var clusterName string
	//Building the main task structure
	defer func() {
		if p := recover(); p != nil {
			tx.Rollback()
			logx.Error(p)
		} else if tx.Error != nil {
			logx.Info("rollback, error", tx.Error)
			tx.Rollback()
		} else {
			tx = tx.Commit()
			logx.Info("commit success")
		}
	}()
	//TODO adapter
	adapterId, _ := strconv.ParseUint(req.AdapterIds[0], 10, 64)
	taskVm := models.TaskVm{}
	//TODO 执行策略返回集群跟 Replica
	opt := &option.VmOption{}
	utils.Convert(&req, &opt)
	// 2、Initialize scheduler
	vmSchdl, _ := schedulers.NewVmScheduler(l.ctx, "", l.svcCtx.Scheduler, opt, l.svcCtx.DbEngin, l.svcCtx.PromClient)
	if err != nil {
		return nil, err
	}
	// 3、Return scheduling results
	results, err := l.svcCtx.Scheduler.AssignAndSchedule(vmSchdl)
	if err != nil {
		logx.Errorf("AssignAndSchedule() => execution error: %v", err)
		return nil, err
	}
	rs := (results).([]*schedulers.VmResult)
	var synergyStatus int64
	if len(rs) > 1 {
		synergyStatus = 1
	}
	var strategy int64
	sqlStr := `select t_dict_item.item_value
			from t_dict
					 left join t_dict_item on t_dict.id = t_dict_item.dict_id
			where item_text = ?
			  and t_dict.dict_code = 'schedule_Strategy'`
	//查询调度策略
	err = tx.Raw(sqlStr, req.Strategy).Scan(&strategy).Error
	taskModel := models.Task{
		Id:              utils.GenSnowflakeID(),
		Status:          constants.Saved,
		Name:            req.Name,
		CommitTime:      time.Now(),
		Description:     "vm task",
		AdapterTypeDict: "0",
		SynergyStatus:   synergyStatus,
		Strategy:        strategy,
	}
	//var taskVms models.TaskVm
	var VmObject types.TaskVm
	for _, r := range rs {
		for _, clusterId := range req.ClusterIds {
			if r.Replica > 0 && r.ClusterId == clusterId {
				fmt.Println("", clusterId)
				sql := `SELECT vi.image_id as image,vf.flavor_id as flavor,vn.network_id as uuid,vi.cluster_name as platform  FROM
	                    vm_flavor vf
	                    LEFT JOIN vm_image vi ON vf.cluster_id = vi.cluster_id 
	                    LEFT JOIN vm_network vn ON vf.cluster_id = vn.cluster_id 
                        WHERE
	                        vi.cluster_id = ?
	                    AND vf.public_flavor_id = ?
	                    AND vi.public_image_id = ?
	                    AND vn.public_network_id = ?`
				txVm := l.svcCtx.DbEngin.Raw(sql, clusterId, req.FlavorRef, req.ImageRef, req.Uuid).Scan(&VmObject)
				if txVm.Error != nil {
					logx.Error(err)
					return nil, txVm.Error
				}
				/*			if err2 != nil {
							logx.Errorf("CommitGeneralTask() => sql execution error: %v", err)
							//return errors.Errorf("the cluster does not match the drive resources. Check the data"), nil
						}*/
				taskVm.Name = req.Name
				taskVm.TaskId = taskModel.Id
				taskVm.Status = "Saved"
				taskVm.StartTime = time.Now().String()
				taskVm.MinCount = req.MinCount
				taskVm.ImageRef = VmObject.Image
				taskVm.FlavorRef = VmObject.Flavor
				taskVm.Uuid = VmObject.Uuid
				taskVm.Platform = VmObject.Platform
				taskVm.AdapterId = int64(adapterId)
				l.svcCtx.DbEngin.Raw("select name from t_adapter where id= ?", int64(adapterId)).Scan(&adaptersName)
				taskVm.AdapterName = adaptersName
				l.svcCtx.DbEngin.Raw("select name from t_cluster where id= ?", r.ClusterId).Scan(&clusterName)
				taskVm.ClusterName = clusterName
				taskVm.ClusterId, err = strconv.ParseInt(clusterId, 10, 64)
				taskVm.VmName = req.VmName
				taskVm.Replicas = req.Replicas
				if err != nil {
					fmt.Println("Error converting string to int64:", err)
					return
				}
				tx = l.svcCtx.DbEngin.Create(&taskVm)
				if tx.Error != nil {
					return nil, tx.Error
				}
			}
		}
	}
	adapterName := ""
	tx.Table("t_adapter").Select("name").Where("id=?", adapterId).Find(&adapterName)
	noticeInfo := clientCore.NoticeInfo{
		AdapterId:   int64(adapterId),
		AdapterName: adapterName,
		NoticeType:  "create",
		TaskName:    req.Name,
		Incident:    "任务创建中",
		CreatedTime: time.Now(),
	}
	// Save task data to database

	tf := l.svcCtx.DbEngin.Create(&taskModel)
	if tf.Error != nil {
		return nil, tf.Error
	}
	result := l.svcCtx.DbEngin.Table("task_vm").Create(&taskVm)
	result = l.svcCtx.DbEngin.Table("t_notice").Create(&noticeInfo)
	if result.Error != nil {
		logx.Errorf("Task creation failure, err: %v", result.Error)
	}

	resp.Code = 200
	resp.Msg = "Success"
	return resp, nil
}
