package cloud

import (
	"context"
	"testing"

	"github.com/crossplane/crossplane-runtime/pkg/meta"
	"github.com/stretchr/testify/require"
	regionalpb "github.com/tidbcloud/infra-provider/api/tidbcloud/regional-server/v1"
	route53v1beta1 "github.com/upbound/provider-aws/apis/route53/v1beta1"
	awsv1beta1 "github.com/upbound/provider-aws/apis/v1beta1"
	apierrors "k8s.io/apimachinery/pkg/api/errors"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/runtime"
	"k8s.io/apimachinery/pkg/types"
	"sigs.k8s.io/controller-runtime/pkg/client"
	"sigs.k8s.io/controller-runtime/pkg/client/fake"
)

func TestBuildProviderConfigBindsRoute53ToAPPBoxAccount(t *testing.T) {
	provider := &aws{
		appbox: &regionalpb.APPBox{
			Kubernetes: &regionalpb.APPBox_Kubernetes{AccountId: "123456789012"},
		},
		assumeRoleName: "ticdc-route53",
		externalID:     "external-id",
	}

	obj, err := provider.BuildProviderConfig(types.NamespacedName{Name: "sinpoint-endpoint"})
	require.NoError(t, err)
	config := obj.(*awsv1beta1.ProviderConfig)
	require.Len(t, config.Spec.AssumeRoleChain, 1)
	require.Equal(t,
		"arn:aws:iam::123456789012:role/ticdc-route53",
		*config.Spec.AssumeRoleChain[0].RoleARN,
	)
	require.Equal(t, "external-id", *config.Spec.AssumeRoleChain[0].ExternalID)
}

func TestDeleteDNSUnpausesRoute53ObjectsBeforeDeletion(t *testing.T) {
	zone := &route53v1beta1.Zone{
		ObjectMeta: metav1.ObjectMeta{
			Name:       "dns-endpoint",
			Finalizers: []string{"finalizer.managedresource.crossplane.io"},
			Annotations: map[string]string{
				meta.AnnotationKeyReconciliationPaused: "true",
			},
		},
	}
	record := &route53v1beta1.Record{
		ObjectMeta: metav1.ObjectMeta{
			Name:   "dns-endpoint-all",
			Labels: map[string]string{"cr-owner.ticdc.tidbcloud.com": zone.Name},
			Annotations: map[string]string{
				meta.AnnotationKeyReconciliationPaused: "true",
			},
		},
	}
	scheme := runtime.NewScheme()
	require.NoError(t, route53v1beta1.AddToScheme(scheme))
	cli := fake.NewClientBuilder().WithScheme(scheme).WithObjects(zone, record).Build()

	err := (&aws{}).DeleteDNS(context.Background(), cli, zone.Name)
	require.ErrorContains(t, err, "delete zone record failed")

	deletedRecord := &route53v1beta1.Record{}
	err = cli.Get(context.Background(), client.ObjectKey{Name: record.Name}, deletedRecord)
	require.True(t, apierrors.IsNotFound(err))

	err = (&aws{}).DeleteDNS(context.Background(), cli, zone.Name)
	require.ErrorContains(t, err, "delete zone failed")

	current := &route53v1beta1.Zone{}
	require.NoError(t, cli.Get(context.Background(), client.ObjectKey{Name: zone.Name}, current))
	require.NotNil(t, current.DeletionTimestamp)
	require.Empty(t, current.Annotations[meta.AnnotationKeyReconciliationPaused])
}
