package event_svc

import (
	"context"
	"errors"
	"fmt"
	"slices"

	eb_event "github.com/tidbcloud/eventbus-datastruct/event"
	"github.com/tidbcloud/pkgv2/tracing"
	"github.com/tidbcloud/serverless-service/internal/domain/constant"
	"github.com/tidbcloud/serverless-service/internal/domain/entity"
	"github.com/tidbcloud/serverless-service/internal/domain/repo"
	"github.com/tidbcloud/serverless-service/internal/metric"
	"github.com/tidbcloud/serverless-service/internal/utils"
	"go.opentelemetry.io/otel"
	"go.uber.org/zap"
)

var Tracer = otel.Tracer("eventsvc")

type SpendLimitService struct {
	clusterTidbPoolRepo repo.ClusterTidbPoolRepo
}

func NewSpendLimitService(
	clusterTidbPoolRepo repo.ClusterTidbPoolRepo,
) *SpendLimitService {
	return &SpendLimitService{clusterTidbPoolRepo}
}

func (s *SpendLimitService) UpdateTidbPoolPolicy(ctx context.Context, event *eb_event.SpendLimitEvent) (err error) {
	ctx, span := Tracer.Start(ctx, "spendlimit.UpdateTidbPoolPolicy")
	logger := utils.GetEventBusLoggerFromContext(ctx).
		With(zap.Uint64("cluster_id", event.RangeID)).
		With(zap.String("event_status", event.Status))

	logger.Info("start to update tidb pool policy")
	if event.Status == constant.SpendLimitEventStatusDeprecated {
		logger.Info("ignore billing event 'deprecated'")
		return nil
	}

	defer func() {
		tracing.EndSpan(span, err)
		logger.Info("save cluster tidb pool settings", zap.Any("error", err))
		status, exitReason := metric.StatusOK, "-"
		if err != nil {
			status = metric.StatusErr
			exitReason = "failed to store spend_limit event to db"
		}
		metric.TidbScheduleEventCounter.WithLabelValues(fmt.Sprint(event.RangeID), "event-bus", event.Status, "-", "-", status, exitReason).
			Inc()
	}()

	if !slices.Contains(constant.SpendLimitValidStatuses, event.Status) {
		return errors.New("invalid Spending Limit event status")
	}

	return s.clusterTidbPoolRepo.Save(ctx, &entity.ClusterTidbPool{
		Type:             constant.TypeSpendLimit,
		ClusterID:        event.RangeID,
		SpendLimitStatus: event.Status,
	})
}
