package resourcemanager

import (
	"context"

	prometheusv1 "github.com/prometheus-operator/prometheus-operator/pkg/apis/monitoring/v1"
	"github.com/tidbcloud/observability/pkg/common/constants"
	"github.com/tidbcloud/observability/pkg/common/errors"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"sigs.k8s.io/controller-runtime/pkg/client"
)

type prometheusRuleReaderWriter struct {
	cli client.Client
}

func (p prometheusRuleReaderWriter) Create(ctx context.Context, data *prometheusv1.PrometheusRule) error {
	return WrapClientError(p.cli.Create(ctx, data))
}

func (p prometheusRuleReaderWriter) IsPrometheusRuleIDExists(ctx context.Context, id string) (bool, error) {
	promRules := new(prometheusv1.PrometheusRuleList)
	matchingLabels := client.MatchingLabels{
		constants.LabelClusterID: id,
	}

	err := p.cli.List(ctx, promRules, matchingLabels)

	if err == nil && len(promRules.Items) > 0 {
		return true, nil
	}

	return false, WrapClientError(err)
}

func (p prometheusRuleReaderWriter) UpdatePrometheusRule(ctx context.Context, data *prometheusv1.PrometheusRule) error {
	return WrapClientError(p.cli.Update(ctx, data))
}

func (p prometheusRuleReaderWriter) GetPrometheusRule(ctx context.Context, id string) (data *prometheusv1.PrometheusRule, err error) {
	prometheusRules := new(prometheusv1.PrometheusRuleList)
	matchingLabels := client.MatchingLabels{
		constants.LabelClusterID: id,
	}

	err = p.cli.List(ctx, prometheusRules,
		matchingLabels,
	)

	if err == nil && len(prometheusRules.Items) == 0 {
		return nil, errors.NewErrorf(errors.PrometheusRuleNotFound, "PrometheusRule %s is not found", id)
	}

	if err == nil && len(prometheusRules.Items) > 0 {
		return prometheusRules.Items[0], nil

	}

	return nil, WrapClientError(err)
}

func (p prometheusRuleReaderWriter) DeletePrometheusRules(ctx context.Context, id string) (err error) {
	promRules, err := p.GetPrometheusRule(ctx, id)
	if err != nil {
		return err
	}
	return p.cli.Delete(ctx, &prometheusv1.PrometheusRule{
		ObjectMeta: metav1.ObjectMeta{
			Name:      id,
			Namespace: promRules.Namespace,
		},
	})
}

func (p prometheusRuleReaderWriter) ListPrometheusRulesInNs(ctx context.Context, ns string) (rules []*prometheusv1.PrometheusRule, err error) {
	prometheusRules := new(prometheusv1.PrometheusRuleList)

	err = p.cli.List(ctx, prometheusRules,
		client.InNamespace(ns),
	)
	if err != nil {
		return nil, WrapClientError(err)
	}
	return prometheusRules.Items, nil

}
