package integration

import (
	"context"
	"fmt"

	"github.com/shiningrush/fastflow/pkg/mod"
	"github.com/tidbcloud/metrics-integration/global/internal/domain/entity"
	"github.com/tidbcloud/metrics-integration/global/internal/infrastructure/di"
	"github.com/tidbcloud/metrics-integration/global/pkg/log"
	mgmt "github.com/tidbcloud/tidb-management-service/api/spec/tidb_mgmt_service/v1"
	clusterevent "github.com/tidbcloud/tidb-management-service/utilities/clusterevent"
	"go.uber.org/zap"
	"gorm.io/gorm"
)

type IntegrationWithClusterResuming struct{}

func (r *IntegrationWithClusterResuming) Name() string {
	return "IntegrationWithClusterResuming"
}

func (r *IntegrationWithClusterResuming) Match(event *clusterevent.ClusterEvent) bool {
	return event.EventType == clusterevent.EventTypeResumed
}

func (r *IntegrationWithClusterResuming) Execute(
	ctx context.Context, event *clusterevent.ClusterEvent, cluster *mgmt.Cluster,
) error {
	logger := log.GetLogger(ctx).Named("IntegrationWithClusterResuming")
	// Additional validation: ensure cluster information is provided and valid
	if cluster == nil || cluster.ClusterId == 0 {
		logger.Error("cluster information is nil, cannot proceed with integration enablement for resuming cluster")
		return fmt.Errorf("cluster information is required to enable integrations for a resuming cluster")
	}
	logger.Info("integration event: CleanUnusedIntegrationClusterJob",
		zap.Uint64("clusterID", cluster.ClusterId))

	// Get all integrations by cluster ID
	var integrations []entity.Integration
	if err := di.DiCall(func(db *gorm.DB) error {
		return db.Model(&entity.Integration{}).
			Where("cluster_id = ? AND status != ?", cluster.ClusterId, entity.IntegrationStatusNone).
			Find(&integrations).Error
	}); err != nil {
		logger.Error("failed to query integrations by cluster ID",
			zap.Uint64("clusterID", cluster.ClusterId),
			zap.Error(err))
		return fmt.Errorf("query integrations failed: %w", err)
	}

	// If no integrations found, no cleanup needed
	if len(integrations) == 0 {
		logger.Info("no active integrations found for cluster",
			zap.Uint64("clusterID", cluster.ClusterId))
		return nil
	}

	logger.Info("found integrations to enable",
		zap.Uint64("clusterID", cluster.ClusterId),
		zap.Int("count", len(integrations)))

	// Enable each integration
	for _, integration := range integrations {
		if err := r.enableIntegration(integration, logger); err != nil {
			logger.Error("failed to enable integration",
				zap.Uint64("integrationID", uint64(integration.ID)),
				zap.Uint64("clusterID", cluster.ClusterId),
				zap.String("providerType", string(integration.ProviderType)),
				zap.Error(err))
			// Continue with other integrations even if one fails
			continue
		}

		logger.Info("successfully enabled integration",
			zap.Uint64("integrationID", uint64(integration.ID)),
			zap.Uint64("clusterID", cluster.ClusterId),
			zap.String("providerType", string(integration.ProviderType)))
	}

	return nil
}

// enableIntegration performs the enabling of a single integration
func (r *IntegrationWithClusterResuming) enableIntegration(integration entity.Integration, logger *zap.Logger) error {
	// Validate integration ID to prevent unauthorized operations
	if integration.ID == 0 {
		logger.Error("integration ID is empty or zero, skipping enabling to prevent unauthorized access",
			zap.Uint64("integrationID", uint64(integration.ID)))
		return fmt.Errorf("invalid integration ID: cannot be empty or zero")
	}

	return di.DiCall(func(db *gorm.DB) error {
		// Run workflow to enable pipeline resources
		if _, err := mod.GetCommander().RunDagWithTags("create-pipeline", map[string]string{
			"id": fmt.Sprintf("%d", integration.ID),
		}, map[string]string{}); err != nil {
			logger.Warn("failed to run create-pipeline workflow, but integration status updated",
				zap.Uint64("integrationID", uint64(integration.ID)),
				zap.Error(err))
			// Don't return error here as the status is already updated
			// The workflow failure is logged but won't block the enabling
		}

		return nil
	})
}
