package clustereventconsumer

import (
	"context"
	"errors"
	"fmt"
	"strconv"

	"github.com/tidbcloud/tiinf/monitor/tilog"
	"github.com/tidbcloud/tiinf/transport/tieventbus"
	"go.uber.org/zap"
	"gorm.io/gorm"

	eventutil "github.com/tidbcloud/tidb-management-service/utilities/clusterevent"
)

func (c *clusterEventConsumerManagerImp) sendToJsmSqs(ctx context.Context, ev *tieventbus.Event) error {
	if !c.jsmClient.IsEnable() {
		tilog.Info(
			ctx,
			"jsm client is not enable, get cluster event",
			zap.String("event id", ev.ID),
			zap.Any("event", ev),
		)
		return nil
	}

	eventBody, ok := ev.Data.(*eventutil.ClusterEvent)
	if !ok {
		tilog.Warn(ctx, "event is not a ClusterEvent", zap.String("event id", ev.ID), zap.Any("event", ev))
		return nil
	}

	if eventBody.ClusterType == eventutil.ClusterTypeTidbxResourcePool {
		tilog.Info(ctx,
			"no need to handle cluster events of resource pool",
			zap.Any("event body", eventBody))
		return nil
	}

	tilog.Info(
		ctx,
		"jsm consumer, try to handle event",
		zap.String("event id", ev.ID),
		zap.Uint64("cluster id", eventBody.ClusterID),
		zap.String("event type", string(eventBody.EventType)),
	)

	if eventBody.EventType != eventutil.EventTypeCreating && eventBody.EventType != eventutil.EventTypeDeleted {
		tilog.Info(
			ctx,
			"event type not need sync to jsm",
			zap.String("event id", ev.ID),
			zap.Uint64("cluster id", eventBody.ClusterID),
			zap.String("event type", string(eventBody.EventType)),
		)
		return nil
	}

	var clusterName string

	// database not serverless only
	cls, err := c.clusterRepo.GetCluster(ctx, eventBody.ClusterID, true)
	if err != nil {
		if !errors.Is(err, gorm.ErrRecordNotFound) {
			err = fmt.Errorf("failed to get cluster. cluster id=%d. error=%w", eventBody.ClusterID, err)
			return err
		}

		tilog.Warn(ctx, "cluster not found.", zap.Uint64("cluster id", eventBody.ClusterID))
		// Call core-svc to get dedicated cluster info.
		// Delete this after migrating to tidb-mgmt-service completely.
		cluster, err := c.coreSvc.GetCluster(ctx, eventBody.ClusterID)
		if err != nil {
			err = fmt.Errorf(
				"failed to get cluster info from core-svc. cluster id=%d. error=%w",
				eventBody.ClusterID,
				err,
			)
			return err
		}
		clusterName = cluster.Name
	} else {
		clusterName = cls.DisplayName
	}

	if err := c.jsmClient.SendClusterEventToJsmSqs(ctx, eventBody, clusterName); err != nil {
		tilog.Error(
			ctx,
			"failed to notify cluster event to jsm",
			zap.String("event id", ev.ID),
			zap.Uint64("cluster id", eventBody.ClusterID),
			zap.String("event type", string(eventBody.EventType)),
			zap.Error(err),
		)
		return err
	}

	syncClusterInfoToJsmFailedTotal.WithLabelValues(strconv.FormatUint(eventBody.ClusterID, 10), clusterName, string(eventBody.EventType)).
		Inc()

	return nil
}
