package k8sresource

import (
	"fmt"
	"slices"

	bizerr "github.com/tidbcloud/infra-provider/regional-server/pkg/common/errors"
	"k8s.io/apimachinery/pkg/runtime/schema"
)

// KindAllowPolicy describes which Kinds are allowed under a Group (map key).
// Exclude=false: Kinds is an allow-list; Exclude=true: Kinds is a deny-list.
type KindAllowPolicy struct {
	Kinds   []string
	Exclude bool
}

// CheckGKAllowed returns an error when the resolved GVK's group/kind is not permitted.
func CheckGKAllowed(gvk schema.GroupVersionKind) error {
	policy, ok := gkAllowlist[gvk.Group]
	if !ok {
		return bizerr.New(bizerr.ParameterInvalid,
			fmt.Sprintf("group %q is not allowed for ListK8sResources", formatGroup(gvk.Group)))
	}
	if len(policy.Kinds) == 0 {
		if policy.Exclude {
			return nil
		}
		return bizerr.New(bizerr.ParameterInvalid,
			fmt.Sprintf("no kinds are allowed for group %q", formatGroup(gvk.Group)))
	}
	inList := slices.Contains(policy.Kinds, gvk.Kind)
	if inList == policy.Exclude {
		return bizerr.New(bizerr.ParameterInvalid,
			fmt.Sprintf("kind %q in group %q is not allowed", gvk.Kind, formatGroup(gvk.Group)))
	}
	return nil
}

func formatGroup(group string) string {
	if group == "" {
		return "core"
	}
	return group
}

// gkAllowlist is the static GK allow policy. Version is not part of the policy.
// Unlisted groups are denied. Exclude=true with empty Kinds allows all kinds in the group.
// Line comments document CP Regional Server RBAC coverage (see dedicated-regional-server RBAC role).
// Trimmed to groups useful for TiDB Cloud cluster deploy/run on-call diagnosis (DP workload + CP infra).
var gkAllowlist = map[string]KindAllowPolicy{
	"":                                       {Exclude: true, Kinds: []string{"Secret"}},                                                                                         // CP RBAC: yes; sensitive: K8s Secret
	"apps":                                   {Exclude: true},                                                                                                                    // CP RBAC: no; DP: yes
	"apps.pingcap.com":                       {Exclude: true},                                                                                                                    // CP RBAC: no; DP: yes
	"autoscaling":                            {Exclude: true},                                                                                                                    // CP RBAC: no; DP: yes
	"aws.crossplane.io":                      {Exclude: true, Kinds: []string{"ProviderConfig"}},                                                                                 // CP RBAC: yes; sensitive: cloud credentials
	"aws.upbound.io":                         {Exclude: true, Kinds: []string{"ProviderConfig", "StoreConfig"}},                                                                  // CP RBAC: yes; sensitive: cloud credentials
	"azure.upbound.io":                       {Exclude: true, Kinds: []string{"ProviderConfig", "StoreConfig"}},                                                                  // CP RBAC: yes; sensitive: cloud credentials
	"batch":                                  {Exclude: true},                                                                                                                    // CP RBAC: no; DP: yes
	"br.pingcap.com":                         {Exclude: true},                                                                                                                    // CP RBAC: no; DP: yes
	"cdc.tidbcloud.com":                      {Exclude: true},                                                                                                                    // CP RBAC: no
	"cloud.google.com":                       {Exclude: true},                                                                                                                    // CP RBAC: no; DP: yes (GCP)
	"cloud.pingcap.com":                      {Exclude: true},                                                                                                                    // CP RBAC: no
	"compute.gcp.crossplane.io":              {Exclude: true},                                                                                                                    // CP RBAC: yes
	"container.gcp.crossplane.io":            {Exclude: true},                                                                                                                    // CP RBAC: yes
	"containerservice.azure.upbound.io":      {Exclude: true},                                                                                                                    // CP RBAC: yes
	"core.pingcap.com":                       {Exclude: true},                                                                                                                    // CP RBAC: no; DP: yes
	"dedicated.regionalserver.tidbcloud.com": {Exclude: true},                                                                                                                    // CP RBAC: yes
	"ec2.aws.crossplane.io":                  {Exclude: true},                                                                                                                    // CP RBAC: yes
	"eks.aws.crossplane.io":                  {Exclude: true},                                                                                                                    // CP RBAC: yes
	"eks.infra.pingcap.com":                  {Exclude: true},                                                                                                                    // CP RBAC: no
	"elbv2.k8s.aws":                          {Exclude: true},                                                                                                                    // CP RBAC: no; DP: yes (AWS)
	"events.k8s.io":                          {Exclude: true},                                                                                                                    // CP RBAC: no; DP: yes
	"gateway.networking.k8s.io":              {Exclude: true},                                                                                                                    // CP RBAC: no; DP: yes
	"gcp.crossplane.io":                      {Exclude: true, Kinds: []string{"ProviderConfig", "StoreConfig"}},                                                                  // CP RBAC: yes; sensitive: cloud credentials
	"gcp.upbound.io":                         {Exclude: true, Kinds: []string{"ProviderConfig", "StoreConfig"}},                                                                  // CP RBAC: no; sensitive: cloud credentials; CP List may 403
	"iam.aws.crossplane.io":                  {Exclude: true, Kinds: []string{"AccessKey"}},                                                                                      // CP RBAC: yes; sensitive: AWS access keys
	"iam.aws.upbound.io":                     {Exclude: true, Kinds: []string{"AccessKey", "UserLoginProfile", "UserSSHKey", "ServiceSpecificCredential", "SigningCertificate"}}, // CP RBAC: yes; sensitive: IAM credentials
	"iam.gcp.crossplane.io":                  {Exclude: true, Kinds: []string{"ServiceAccountKey"}},                                                                              // CP RBAC: yes; sensitive: GCP SA keys
	"network.azure.upbound.io":               {Exclude: true},                                                                                                                    // CP RBAC: yes
	"networking.gke.io":                      {Exclude: true},                                                                                                                    // CP RBAC: no; DP: yes (GCP)
	"networking.k8s.aws":                     {Exclude: true},                                                                                                                    // CP RBAC: no; DP: yes (AWS)
	"networking.k8s.io":                      {Exclude: true},                                                                                                                    // CP RBAC: no; DP: yes
	"node.gke.io":                            {Exclude: true},                                                                                                                    // CP RBAC: no; DP: yes (GCP)
	"pingcap.com":                            {Exclude: true},                                                                                                                    // CP RBAC: no; DP: yes
	"route53.aws.crossplane.io":              {Exclude: true},                                                                                                                    // CP RBAC: yes
	"snapshot.storage.k8s.io":                {Exclude: true},                                                                                                                    // CP RBAC: no; DP: yes (GCP)
	"storage.gcp.crossplane.io":              {Exclude: true},                                                                                                                    // CP RBAC: yes
	"storage.k8s.io":                         {Exclude: true},                                                                                                                    // CP RBAC: no; DP: yes
	"vpcpeering.gcp.crossplane.io":           {Exclude: true},                                                                                                                    // CP RBAC: yes
	"vpcresources.k8s.aws":                   {Exclude: true},                                                                                                                    // CP RBAC: no; DP: yes (AWS)
}
