package k8sresource

import (
	"encoding/json"
	"testing"

	"github.com/tidbcloud/infra-provider/pkg/consts"
	"k8s.io/apimachinery/pkg/apis/meta/v1/unstructured"
	"k8s.io/apimachinery/pkg/runtime/schema"
)

func TestSanitizeObjectForDetail(t *testing.T) {
	obj := &unstructured.Unstructured{Object: map[string]any{
		"metadata": map[string]any{
			"name": "test",
			"annotations": map[string]any{
				kubectlLastAppliedConfigurationAnnotation: `{"apiVersion":"v1"}`,
				consts.LastAppliedConfigAnnotation:        `{"spec":{}}`,
				"keep-me": "value",
			},
			"managedFields": []any{
				map[string]any{"manager": "kubectl"},
			},
		},
	}}
	gvk := schema.GroupVersionKind{Group: "", Version: "v1", Kind: "Pod"}

	SanitizeObjectForDetail(gvk, obj)

	ann := obj.GetAnnotations()
	if ann == nil {
		t.Fatal("expected annotations to remain")
	}
	if _, ok := ann[kubectlLastAppliedConfigurationAnnotation]; ok {
		t.Fatal("kubectl last-applied annotation should be removed")
	}
	if _, ok := ann[consts.LastAppliedConfigAnnotation]; ok {
		t.Fatal("tidbcloud last-applied annotation should be removed")
	}
	if ann["keep-me"] != "value" {
		t.Fatal("unrelated annotation should be kept")
	}
	if obj.GetManagedFields() != nil {
		t.Fatal("managedFields should be cleared")
	}
}

func TestApplyGKMask_Cluster(t *testing.T) {
	obj := &unstructured.Unstructured{Object: map[string]any{
		"spec": map[string]any{
			"kubernetes": map[string]any{
				"caData": "secret-ca",
			},
		},
		"status": map[string]any{
			"sqlEndpoints": map[string]any{
				"publicEndpoint": map[string]any{
					"token": "secret-token",
				},
			},
		},
	}}
	gvk := schema.GroupVersionKind{Group: "cloud.pingcap.com", Version: "v1", Kind: "Cluster"}

	ApplyGKMask(gvk, obj)

	caData, found, err := unstructured.NestedString(obj.Object, "spec", "kubernetes", "caData")
	if err != nil || !found {
		t.Fatalf("expected caData field, err=%v found=%v", err, found)
	}
	if caData != sensitiveDataMask {
		t.Fatalf("caData = %q, want %q", caData, sensitiveDataMask)
	}
	token, found, err := unstructured.NestedString(obj.Object, "status", "sqlEndpoints", "publicEndpoint", "token")
	if err != nil || !found {
		t.Fatalf("expected token field, err=%v found=%v", err, found)
	}
	if token != sensitiveDataMask {
		t.Fatalf("token = %q, want %q", token, sensitiveDataMask)
	}
}

func TestApplyGKMask_APPRoute(t *testing.T) {
	forCluster := `{"id":"10140697173347482530","tenantId":"60178","securityConfigurations":{"tidbAuthTokenJwks":"{\"keys\":[{\"kty\":\"RSA\"}]}"}}`
	obj := &unstructured.Unstructured{Object: map[string]any{
		"spec": map[string]any{
			"forCluster": forCluster,
		},
	}}
	gvk := schema.GroupVersionKind{
		Group:   "dedicated.regionalserver.tidbcloud.com",
		Version: "v1alpha1",
		Kind:    "APPRoute",
	}

	ApplyGKMask(gvk, obj)

	maskedForCluster, found, err := unstructured.NestedString(obj.Object, "spec", "forCluster")
	if err != nil || !found {
		t.Fatalf("expected forCluster field, err=%v found=%v", err, found)
	}
	var cluster map[string]any
	if err := json.Unmarshal([]byte(maskedForCluster), &cluster); err != nil {
		t.Fatalf("forCluster should remain valid JSON: %v", err)
	}
	jwks, found, err := unstructured.NestedString(cluster, "securityConfigurations", "tidbAuthTokenJwks")
	if err != nil || !found {
		t.Fatalf("expected tidbAuthTokenJwks field, err=%v found=%v", err, found)
	}
	if jwks != sensitiveDataMask {
		t.Fatalf("tidbAuthTokenJwks = %q, want %q", jwks, sensitiveDataMask)
	}
	id, found, err := unstructured.NestedString(cluster, "id")
	if err != nil || !found {
		t.Fatalf("expected id field, err=%v found=%v", err, found)
	}
	if id != "10140697173347482530" {
		t.Fatalf("id = %q, want %q", id, "10140697173347482530")
	}
	tenantID, found, err := unstructured.NestedString(cluster, "tenantId")
	if err != nil || !found {
		t.Fatalf("expected tenantId field, err=%v found=%v", err, found)
	}
	if tenantID != "60178" {
		t.Fatalf("tenantId = %q, want %q", tenantID, "60178")
	}
}

func TestApplyGKMask_APPRoute_invalidForClusterJSON(t *testing.T) {
	invalidForCluster := "not-json"
	obj := &unstructured.Unstructured{Object: map[string]any{
		"spec": map[string]any{
			"forCluster": invalidForCluster,
		},
	}}
	gvk := schema.GroupVersionKind{
		Group:   "dedicated.regionalserver.tidbcloud.com",
		Version: "v1alpha1",
		Kind:    "APPRoute",
	}

	ApplyGKMask(gvk, obj)

	forCluster, found, err := unstructured.NestedString(obj.Object, "spec", "forCluster")
	if err != nil || !found {
		t.Fatalf("expected forCluster field, err=%v found=%v", err, found)
	}
	if forCluster != invalidForCluster {
		t.Fatalf("forCluster = %q, want unchanged %q", forCluster, invalidForCluster)
	}
}

func TestApplyGKMask_Replay(t *testing.T) {
	obj := &unstructured.Unstructured{Object: map[string]any{
		"spec": map[string]any{
			"kubernetes": map[string]any{
				"caData": "secret-ca",
			},
		},
	}}
	gvk := schema.GroupVersionKind{Group: "cloud.pingcap.com", Version: "v1", Kind: "Replay"}

	ApplyGKMask(gvk, obj)

	caData, found, err := unstructured.NestedString(obj.Object, "spec", "kubernetes", "caData")
	if err != nil || !found {
		t.Fatalf("expected caData field, err=%v found=%v", err, found)
	}
	if caData != sensitiveDataMask {
		t.Fatalf("caData = %q, want %q", caData, sensitiveDataMask)
	}
}
