package impl

import (
	"context"
	"sort"
	"strings"

	"github.com/tidbcloud/dataflow-service/app/internal/feature_gate"
	"github.com/tidbcloud/dataflow-service/app/models/domain"
	"github.com/tidbcloud/dataflow-service/internal/config"
	"github.com/tidbcloud/dataflow-service/pkg/log"
	"go.uber.org/zap"
)

var _ feature_gate.FeatureGate = &featureGateV2{}

// featureGateV2 is the new implementation of FeatureGate interface based on config.FeatureGate.
type featureGateV2 struct{}

func NewFeatureGateV2() feature_gate.FeatureGate {
	return &featureGateV2{}
}

func (f *featureGateV2) QueryEnabledFeatures(req *feature_gate.QueryFeatureGateReq) feature_gate.QueryFeatureGateResp {
	featureGates := config.Global().ServerConfig.FeatureGates

	var features []string
	for featureName := range featureGates {
		if f.IsFeatureEnabled(req, featureName) {
			features = append(features, strings.ToLower(featureName))
		}
	}

	sort.Strings(features)
	return feature_gate.QueryFeatureGateResp{Features: features}
}

func (f *featureGateV2) IsFeatureEnabled(req *feature_gate.QueryFeatureGateReq, feature string) bool {
	lg := log.GetLogger(context.TODO())
	featureGates := config.Global().ServerConfig.FeatureGates
	gate, exists := featureGates[feature]
	if !exists {
		return false
	}

	params := f.buildQueryParams(req)
	msg, enabled := gate.Enabled(params)
	lg.Debug("feature gate check", zap.String("feature", feature), zap.Bool("enabled", enabled), zap.String("msg", msg))
	return enabled
}

// buildQueryParams converts feature_gate.QueryFeatureGateReq to config.FeatureGateQueryParams.
// It handles InfraProvider (eks/gke/aks) to Provider (aws/gcp/azure) conversion.
func (f *featureGateV2) buildQueryParams(req *feature_gate.QueryFeatureGateReq) config.FeatureGateQueryParams {
	params := config.FeatureGateQueryParams{
		Region:    req.Region,
		TenantID:  req.TenantID,
		ProjectID: req.ProjectID,
		ClusterID: req.ClusterID,
	}

	// Convert InfraProvider (eks/gke/aks) to Provider (aws/gcp/azure)
	if req.InfraProvider != "" {
		cloudProvider := domain.InfraProviderType2CloudProviderType(
			domain.InfraProviderType(req.InfraProvider),
		)
		params.Provider = string(cloudProvider)
	}

	return params
}
