package monitoring

import (
	"context"
	v1 "github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring/v1"
	"github.com/zeromicro/go-zero/core/logx"
	"gitlink.org.cn/JointCloud/pcm-coordinator/internal/svc"
	"gitlink.org.cn/JointCloud/pcm-coordinator/internal/types"
	"gitlink.org.cn/JointCloud/pcm-coordinator/pkg/models"
	tool "gitlink.org.cn/JointCloud/pcm-coordinator/pkg/utils"
	v12 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/util/intstr"
	"k8s.io/apimachinery/pkg/util/json"
	"strconv"
)

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

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

type RuleSelectorResp struct {
	Code       int           `json:"code"`
	Msg        string        `json:"msg"`
	Prometheus v1.Prometheus `json:"data"`
}

func (l *CreateAlertRuleLogic) CreateAlertRule(req *types.CreateAlertRuleReq) error {

	// save to db
	var alertRule models.AlertRule
	tool.Convert(req, &alertRule)
	alertRule.ClusterId, _ = strconv.ParseInt(req.CLusterId, 10, 64)
	alertRule.Id = tool.GenSnowflakeID()
	tx := l.svcCtx.DbEngin.Save(&alertRule)
	if tx.Error != nil {
		return tx.Error
	}

	// query cluster http url.
	var server string
	l.svcCtx.DbEngin.Raw("select ta.server from t_adapter ta,t_cluster tc where ta.id = tc.adapter_id and tc.name = ?", &req.ClusterName).Scan(&server)

	// rule selector
	var ruleSelectorResp RuleSelectorResp

	response, err := l.svcCtx.HttpClient.R().
		SetQueryParams(map[string]string{
			"clusterName": req.ClusterName,
		}).
		SetResult(&ruleSelectorResp).
		ForceContentType("application/json").
		Get(server + "/api/v1/monitoring/rule/selector")
	if err != nil || response.IsError() {
		logx.Error(response)
		return err
	}
	// Data Filling
	ruleDuration := v1.Duration(req.Duration)
	rule := &v1.PrometheusRule{
		TypeMeta: v12.TypeMeta{Kind: "PrometheusRule",
			APIVersion: "monitoring.coreos.com/v1"},
		ObjectMeta: v12.ObjectMeta{
			Name:      req.Name,
			Namespace: ruleSelectorResp.Prometheus.ObjectMeta.Namespace,
			Labels:    ruleSelectorResp.Prometheus.Spec.RuleSelector.MatchLabels,
		},
		Spec: v1.PrometheusRuleSpec{
			Groups: []v1.RuleGroup{
				{
					Name: "example-group",
					Rules: []v1.Rule{
						{
							Alert: req.Name,
							Expr:  intstr.FromString(req.PromQL),
							For:   &ruleDuration,
							Labels: map[string]string{
								"severity": req.AlertLevel,
							},
							Annotations: map[string]string{"description": req.Annotations},
						},
					},
				},
			},
		},
	}

	ruleBytes, err := json.Marshal(rule)
	if err != nil {
		return err
	}

	// create prometheus rule
	response, err = l.svcCtx.HttpClient.R().
		SetBody(&OperateStruct{
			ClusterName: req.ClusterName,
			YamlString:  string(ruleBytes),
		}).
		ForceContentType("application/json").
		Post(server + "/api/v1/operate/apply")
	if err != nil || response.IsError() {
		return err
	}

	return nil
}

type OperateStruct struct {
	ClusterName string `json:"clusterName"`
	YamlString  string `json:"yamlString"`
}
