package featuregate

import "slices"

type FeatureGate struct {
	// First, the feature gate will be disabled for these tenants, projects or regions.
	DisabledTenants        []uint64 `mapstructure:"disabledTenants"`
	DisabledProjects       []uint64 `mapstructure:"disabledProjects"`
	DisabledCloudProviders []string `mapstructure:"disabledCloudProviders"`
	DisabledRegions        []string `mapstructure:"disabledRegions"`

	// Then, the feature gate will be enabled for these tenants, projects, regions or orgs created after a specific date.
	EnabledTenants        []uint64 `mapstructure:"enabledTenants"`
	EnabledProjects       []uint64 `mapstructure:"enabledProjects"`
	EnabledCloudProviders []string `mapstructure:"enabledCloudProviders"`
	EnabledRegions        []string `mapstructure:"enabledRegions"`
	AffectOrgCreatedAfter string   `mapstructure:"affectOrgCreatedAfter" default:""`

	// Finally, the feature gate will be enabled or disable for all tenants.
	All bool `mapstructure:"all" default:"false"`
}

// Check determines if the feature is enabled for the given tenant, project, cloud provider, and region
// based on the configured blacklist and whitelist rules.
// Returns (enabled, determined) where determined indicates if a definitive decision was made.
//
// Recommended to use CheckWithAll instead to consider the All field as a fallback.
func (fg *FeatureGate) Check(
	tenantID, projectID uint64,
	cloudProvider, region string,
) (enabled, determined bool) {
	// Blacklist
	// Check if it's disabled for the tenant.
	if slices.Contains(fg.DisabledTenants, tenantID) {
		return false, true
	}
	// Check if it's disabled for the project.
	if slices.Contains(fg.DisabledProjects, projectID) {
		return false, true
	}
	// Check if it's disabled for the cloud provider.
	if slices.Contains(fg.DisabledCloudProviders, cloudProvider) {
		return false, true
	}
	// Check if it's disabled for the region.
	if slices.Contains(fg.DisabledRegions, region) {
		return false, true
	}

	// Whitelist
	// Check if it's enabled for the tenant.
	if slices.Contains(fg.EnabledTenants, tenantID) {
		return true, true
	}
	// Check if it's enabled for the project.
	if slices.Contains(fg.EnabledProjects, projectID) {
		return true, true
	}
	// Check if it's enabled for the cloud provider.
	if slices.Contains(fg.EnabledCloudProviders, cloudProvider) {
		return true, true
	}
	// Check if it's enabled for the region.
	if slices.Contains(fg.EnabledRegions, region) {
		return true, true
	}

	return false, false
}

// CheckWithAll checks if the feature is enabled for the given tenant, project, cloud provider, and region.
// If the check is determined (blacklisted or whitelisted), it returns that result.
// Otherwise, it falls back to the All field value.
func (fg *FeatureGate) CheckWithAll(
	tenantID, projectID uint64,
	cloudProvider, region string,
) bool {
	if enabled, determined := fg.Check(tenantID, projectID, cloudProvider, region); determined {
		return enabled
	}

	return fg.All
}
