package apps

import (
	"context"
	"gitlink.org.cn/JointCloud/pcm-kubernetes/kubernetes"
	"gorm.io/datatypes"
	"gorm.io/gorm"
	"time"

	"gitlink.org.cn/JointCloud/pcm-coordinator/api/internal/svc"
	"gitlink.org.cn/JointCloud/pcm-coordinator/api/internal/types"

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

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

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

type Task struct {
	Id            int64          `db:"id"`             // id
	Name          string         `db:"name"`           // 作业名称
	Description   string         `db:"description"`    // 作业描述
	Status        string         `db:"status"`         // 作业状态
	Strategy      int64          `db:"strategy"`       // 策略
	SynergyStatus int64          `db:"synergy_status"` // 协同状态（0-未协同、1-已协同）
	CommitTime    time.Time      `db:"commit_time"`    // 提交时间
	StartTime     string         `db:"start_time"`     // 开始时间
	EndTime       string         `db:"end_time"`       // 结束运行时间
	RunningTime   int64          `db:"running_time"`   // 已运行时间（单位秒）
	YamlString    datatypes.JSON `db:"yaml_string"`
	Result        string         `db:"result"` // 作业结果
	DeletedAt     gorm.DeletedAt `gorm:"index"`
	NsID          string         `db:"ns_id"`
	PName         string         `db:"p_name"` // p端名称
	PId           int64          `db:"p_id"`   // p端id
}

func (l *AppListLogic) AppList(req *types.AppListReq) (resp *types.AppListResp, err error) {
	var tasks []Task
	resp = &types.AppListResp{}
	l.svcCtx.DbEngin.Raw("select * from task t where t.`ns_id` = ? AND t.`deleted_at` IS NULL ORDER BY t.created_time Desc", req.NsID).Scan(&tasks)
	for _, task := range tasks {
		//调用p端接口查询应用状态 running、creating、waiting、error、pause
		data, err := l.svcCtx.K8sRpc.GetAppByAppName(context.Background(), &kubernetes.DeploymentDetailReq{
			Namespace: req.NsID,
			Name:      task.Name,
		})
		if err != nil {
			logx.Errorf("调用p端接口查询应用失败，err:%v", err)
			return resp, err
		}
		minReplicas := ""
		maxReplicas := ""
		status := "creating"
		if data.Data.Deployment != nil {
			app := data.Data.Deployment
			maxReplicas = app.Metadata.Annotations["deploy.cloud.sealos.io/maxReplicas"]
			minReplicas = app.Metadata.Annotations["deploy.cloud.sealos.io/minReplicas"]
			if app.Status != nil {
				if app.Status.Replicas == nil && app.Status.AvailableReplicas == nil {
					status = "pause"
				} else if app.Status.Replicas != nil && app.Status.AvailableReplicas == nil {
					status = "creating"
				} else if *app.Status.Replicas == *app.Status.AvailableReplicas {
					status = "running"
				}
			}
		} else if data.Data.StatefulSet != nil {
			app := data.Data.StatefulSet
			maxReplicas = app.Metadata.Annotations["deploy.cloud.sealos.io/maxReplicas"]
			minReplicas = app.Metadata.Annotations["deploy.cloud.sealos.io/minReplicas"]
			if app.Status != nil {
				replicas := app.Status.Replicas
				availableReplicas := app.Status.AvailableReplicas
				if *replicas == 0 && *availableReplicas == 0 {
					status = "pause"
				} else if *replicas == *availableReplicas {
					status = "running"
				} else if *replicas > *availableReplicas {
					status = "creating"
				}
			}
		}
		var details []types.AppLocation
		sql :=
			`select phy.id as participant_id, phy.name as participant_name, c.kind
			from cloud c
					 join sc_participant_phy_info phy on c.participant_id = phy.id
			WHERE c.kind in ('Deployment', 'StatefulSet')
			  and task_id = ?`
		l.svcCtx.DbEngin.Raw(sql, task.Id).Scan(&details)
		resp.Apps = append(resp.Apps, types.App{
			Id:           task.Id,
			Name:         task.Name,
			Status:       status,
			CreateTime:   task.CommitTime.Format("2006-01-02 15:04:05"),
			MinReplicas:  minReplicas,
			MaxReplicas:  maxReplicas,
			AppLocations: details,
		})
	}
	return
}
