package facade_imp

import (
	"context"
	"fmt"
	"strconv"

	"github.com/tidbcloud/pkgv2/log"
	"github.com/tidbcloud/serverless-service/internal/config"
	"github.com/tidbcloud/serverless-service/internal/domain/constant"
	"github.com/tidbcloud/serverless-service/internal/domain/facade"
)

type featureGate struct {
	enabledAll     bool
	enabledTenants map[uint64]bool
}

type FeatureGateImp struct {
	featureGates map[constant.FeatureGateName]featureGate
}

func NewFeatureGateImp() facade.FeatureGate {
	f := &FeatureGateImp{}
	if err := f.Refresh(); err != nil {
		panic(err)
	}
	return f
}

func (f *FeatureGateImp) Refresh() error {
	featureGates := make(map[constant.FeatureGateName]featureGate)
	for name, gates := range config.Global().FeatureGates {
		if len(gates.EnabledTenants) == 0 {
			log.Info(context.TODO(), "feature gate configured without enabledTenants")
			continue
		}

		enabledAll := false
		tenants := make(map[uint64]bool)
		for _, v := range gates.EnabledTenants {
			if v == "*" {
				enabledAll = true
				break
			}
			tenantId, err := strconv.ParseUint(v, 10, 0)
			if err != nil {
				return fmt.Errorf("feature gate configured with invalid tenant id: %s", v)
			}
			tenants[tenantId] = true
		}
		featureGates[name] = featureGate{
			enabledAll:     enabledAll,
			enabledTenants: tenants,
		}
	}

	f.featureGates = featureGates
	return nil
}

func (f *FeatureGateImp) FeatureEnabled(featureName constant.FeatureGateName, tenantID uint64, region string) bool {
	gates, ok := f.featureGates[featureName]
	if !ok {
		return false
	}
	if gates.enabledAll {
		return true
	}

	return gates.enabledTenants[tenantID]
}

func (f *FeatureGateImp) ListFeatureEnabledTenants(featureName constant.FeatureGateName) []uint64 {
	result := make([]uint64, 0, 5)
	gates, ok := f.featureGates[featureName]
	if !ok {
		return result
	}

	for k := range gates.enabledTenants {
		result = append(result, k)
	}
	return result
}
