package userbehavior

import (
	"context"
	"fmt"
	"strings"

	"github.com/expr-lang/expr"
	larkcard "github.com/larksuite/oapi-sdk-go/v3/card"
	ubent "github.com/tidbcloud/devops/entity/userbehavior"
	evbus "github.com/tidbcloud/eventbus-datastruct/event"
)

type cdcUBEvent struct {
	originEv             *evbus.DisplayEvent
	tenantName           *string
	tenantID             uint64
	tenantAlias          *string
	bizRegion            *string
	clusterID            uint64
	clusterName          *string
	cdcBehaviorPredicate *string
	extraInfo            string
}

var acceptedCdcEvents = []evbus.EventStatus{
	evbus.EventStatusStarted,
	evbus.EventStatusSucceeded,
	evbus.EventStatusFailed,
	evbus.EventStatusCanceled,
	evbus.EventStatusPaused,
}

func (event *cdcUBEvent) HandleUBEvent(ctx context.Context) error {
	return nil
}

func (event *cdcUBEvent) PreProcess(ctx context.Context) error {
	return nil
}

func (event *cdcUBEvent) PostProcess(ctx context.Context) error {
	return nil
}

func (event *cdcUBEvent) ProcessTemplate(ctx context.Context, template string) (string, error) {
	return template, nil
}

func (event *cdcUBEvent) DefaultText(ctx context.Context) string {
	var tenantName, tenantAlias string
	if event.tenantName != nil {
		tenantName = *event.tenantName
	}
	if event.tenantAlias != nil {
		tenantAlias = *event.tenantAlias
	}

	return fmt.Sprintf("[** %s **] Tenant** %s **(%d, alias: %s) ** %s ** a changefeed. Cluster: ** %s **(%d)\nDetail: %s",
		*event.bizRegion,
		tenantName,
		event.tenantID,
		tenantAlias,
		*event.cdcBehaviorPredicate,
		*event.clusterName,
		event.clusterID,
		event.extraInfo,
	)
}

func (event *cdcUBEvent) GetAvailableParams(ctx context.Context) []string {
	return clusterEventParams
}

func (event *cdcUBEvent) GetUBEventType() ubent.UBEventTp {
	return ubent.UBEventCDC
}

func (event *cdcUBEvent) CustomFilter(ctx context.Context, textFilter string) (ret bool, err error) {
	program, err := expr.Compile(textFilter)
	if err != nil {
		return ret, err
	}

	output, err := expr.Run(program, event.originEv)
	if err != nil {
		return ret, err
	}
	ret, ok := output.(bool)
	if !ok {
		return ret, fmt.Errorf("not return a bool type")
	}

	return ret, nil
}

func newCDCUBEvent(ev *evbus.DisplayEvent) UBEvent {
	predicate := convertDisplayEventType2Predicate(ev.DisplayEventType)
	ubEvent := cdcUBEvent{
		originEv:             ev,
		tenantName:           nil,
		tenantAlias:          nil,
		bizRegion:            nil,
		tenantID:             ev.TenantID,
		clusterID:            ev.ClusterID,
		cdcBehaviorPredicate: &predicate,
		extraInfo:            ev.Summary,
	}

	return &ubEvent
}

func convertDisplayEventType2Predicate(displayTp string) string {
	// HACK
	return strings.ToLower(strings.Replace(displayTp, "Changefeed", "", 1))
}

func (e *cdcUBEvent) BuildCustomCard(ctx context.Context) (*larkcard.MessageCard, error) {
	return nil, nil // Use standard card
}
