package regionalservercli_test

import (
	"context"
	"net/http"
	"testing"

	"github.com/jarcoal/httpmock"
	"github.com/stretchr/testify/require"
	"github.com/tidbcloud/infra-provider/regional-server/pkg/common/regionalservercli"
	"sigs.k8s.io/controller-runtime/pkg/client"

	awsiamv1beta1 "github.com/crossplane-contrib/provider-aws/apis/iam/v1beta1"
	computev1alpha1 "github.com/crossplane-contrib/provider-gcp/apis/compute/v1alpha1"
	computev1beta1 "github.com/crossplane-contrib/provider-gcp/apis/compute/v1beta1"
	containerv1beta1 "github.com/crossplane-contrib/provider-gcp/apis/container/v1beta1"
	containerv1beta2 "github.com/crossplane-contrib/provider-gcp/apis/container/v1beta2"
	gcpiamv1alpha1 "github.com/crossplane-contrib/provider-gcp/apis/iam/v1alpha1"
	storagev1alpha1 "github.com/crossplane-contrib/provider-gcp/apis/storage/v1alpha1"
	xpv1beta1 "github.com/crossplane-contrib/provider-gcp/apis/v1beta1"
	vpcpeeringv1beta1 "github.com/crossplane/provider-gcp/apis/vpcpeering/v1beta1"
)

// TestMigrationAWSClient just test path and method are correct
func TestMigrationGCPClient(t *testing.T) {
	ctx := context.Background()
	httpmock.Activate()
	defer httpmock.DeactivateAndReset()
	successHandlerFunc := func(r *http.Request) (*http.Response, error) {
		return httpmock.NewJsonResponse(http.StatusOK, struct{}{})
	}
	reconcileHandlerFunc := func(r *http.Request) (*http.Response, error) {
		q := r.URL.Query()
		if q.Get("pause") != "false" && q.Get("pause") != "true" {
			return httpmock.NewJsonResponse(http.StatusBadRequest, struct{}{})
		}
		return httpmock.NewJsonResponse(http.StatusOK, struct{}{})
	}

	notFoundHandlerFunc := func(r *http.Request) (*http.Response, error) {
		t.Logf("not found handler for url: %+v\n", r.URL.String())
		return httpmock.NewJsonResponse(http.StatusNotFound, struct{}{})
	}
	httpmock.RegisterNoResponder(notFoundHandlerFunc)
	httpmock.RegisterResponder(http.MethodPost, "/api/dedicated/v1/migration/crossplane/gcp/import/address", successHandlerFunc)
	httpmock.RegisterResponder(http.MethodPost, "/api/dedicated/v1/migration/crossplane/gcp/import/firewall", successHandlerFunc)
	httpmock.RegisterResponder(http.MethodPost, "/api/dedicated/v1/migration/crossplane/gcp/import/network", successHandlerFunc)
	httpmock.RegisterResponder(http.MethodPost, "/api/dedicated/v1/migration/crossplane/gcp/import/router", successHandlerFunc)
	httpmock.RegisterResponder(http.MethodPost, "/api/dedicated/v1/migration/crossplane/gcp/import/subnetwork", successHandlerFunc)
	httpmock.RegisterResponder(http.MethodPost, "/api/dedicated/v1/migration/crossplane/gcp/import/cluster", successHandlerFunc)
	httpmock.RegisterResponder(http.MethodPost, "/api/dedicated/v1/migration/crossplane/gcp/import/nodepool", successHandlerFunc)
	httpmock.RegisterResponder(http.MethodPost, "/api/dedicated/v1/migration/crossplane/gcp/import/providerconfig", successHandlerFunc)
	httpmock.RegisterResponder(http.MethodPost, "/api/dedicated/v1/migration/crossplane/gcp/import/serviceaccountkey", successHandlerFunc)
	httpmock.RegisterResponder(http.MethodPost, "/api/dedicated/v1/migration/crossplane/gcp/import/serviceaccountpolicy", successHandlerFunc)
	httpmock.RegisterResponder(http.MethodPost, "/api/dedicated/v1/migration/crossplane/gcp/import/serviceaccount", successHandlerFunc)
	httpmock.RegisterResponder(http.MethodPost, "/api/dedicated/v1/migration/crossplane/gcp/import/bucketpolicymember", successHandlerFunc)
	httpmock.RegisterResponder(http.MethodPost, "/api/dedicated/v1/migration/crossplane/gcp/import/peering", successHandlerFunc)
	httpmock.RegisterResponder(http.MethodPost, "/api/dedicated/v1/migration/crossplane/gcp/import/openidconnectprovider", successHandlerFunc)
	httpmock.RegisterResponder(http.MethodPost, "/api/dedicated/v1/migration/crossplane/gcp/import/policy", successHandlerFunc)
	httpmock.RegisterResponder(http.MethodPost, "/api/dedicated/v1/migration/crossplane/gcp/import/rolepolicyattachment", successHandlerFunc)
	httpmock.RegisterResponder(http.MethodPost, "/api/dedicated/v1/migration/crossplane/gcp/import/role", successHandlerFunc)

	httpmock.RegisterResponder(http.MethodGet, "/api/dedicated/v1/migration/crossplane/gcp/check/address", successHandlerFunc)
	httpmock.RegisterResponder(http.MethodGet, "/api/dedicated/v1/migration/crossplane/gcp/check/firewall", successHandlerFunc)
	httpmock.RegisterResponder(http.MethodGet, "/api/dedicated/v1/migration/crossplane/gcp/check/network", successHandlerFunc)
	httpmock.RegisterResponder(http.MethodGet, "/api/dedicated/v1/migration/crossplane/gcp/check/router", successHandlerFunc)
	httpmock.RegisterResponder(http.MethodGet, "/api/dedicated/v1/migration/crossplane/gcp/check/subnetwork", successHandlerFunc)
	httpmock.RegisterResponder(http.MethodGet, "/api/dedicated/v1/migration/crossplane/gcp/check/cluster", successHandlerFunc)
	httpmock.RegisterResponder(http.MethodGet, "/api/dedicated/v1/migration/crossplane/gcp/check/nodepool", successHandlerFunc)
	httpmock.RegisterResponder(http.MethodGet, "/api/dedicated/v1/migration/crossplane/gcp/check/serviceaccountkey", successHandlerFunc)
	httpmock.RegisterResponder(http.MethodGet, "/api/dedicated/v1/migration/crossplane/gcp/check/serviceaccountpolicy", successHandlerFunc)
	httpmock.RegisterResponder(http.MethodGet, "/api/dedicated/v1/migration/crossplane/gcp/check/serviceaccount", successHandlerFunc)
	httpmock.RegisterResponder(http.MethodGet, "/api/dedicated/v1/migration/crossplane/gcp/check/bucketpolicymember", successHandlerFunc)
	httpmock.RegisterResponder(http.MethodGet, "/api/dedicated/v1/migration/crossplane/gcp/check/peering", successHandlerFunc)
	httpmock.RegisterResponder(http.MethodGet, "/api/dedicated/v1/migration/crossplane/gcp/check/openidconnectprovider", successHandlerFunc)
	httpmock.RegisterResponder(http.MethodGet, "/api/dedicated/v1/migration/crossplane/gcp/check/policy", successHandlerFunc)
	httpmock.RegisterResponder(http.MethodGet, "/api/dedicated/v1/migration/crossplane/gcp/check/rolepolicyattachment", successHandlerFunc)
	httpmock.RegisterResponder(http.MethodGet, "/api/dedicated/v1/migration/crossplane/gcp/check/role", successHandlerFunc)

	httpmock.RegisterResponder(http.MethodPatch, "/api/dedicated/v1/migration/crossplane/gcp/reconcile/address", reconcileHandlerFunc)
	httpmock.RegisterResponder(http.MethodPatch, "/api/dedicated/v1/migration/crossplane/gcp/reconcile/firewall", reconcileHandlerFunc)
	httpmock.RegisterResponder(http.MethodPatch, "/api/dedicated/v1/migration/crossplane/gcp/reconcile/network", reconcileHandlerFunc)
	httpmock.RegisterResponder(http.MethodPatch, "/api/dedicated/v1/migration/crossplane/gcp/reconcile/router", reconcileHandlerFunc)
	httpmock.RegisterResponder(http.MethodPatch, "/api/dedicated/v1/migration/crossplane/gcp/reconcile/subnetwork", reconcileHandlerFunc)
	httpmock.RegisterResponder(http.MethodPatch, "/api/dedicated/v1/migration/crossplane/gcp/reconcile/cluster", reconcileHandlerFunc)
	httpmock.RegisterResponder(http.MethodPatch, "/api/dedicated/v1/migration/crossplane/gcp/reconcile/nodepool", reconcileHandlerFunc)
	httpmock.RegisterResponder(http.MethodPatch, "/api/dedicated/v1/migration/crossplane/gcp/reconcile/serviceaccountkey", reconcileHandlerFunc)
	httpmock.RegisterResponder(http.MethodPatch, "/api/dedicated/v1/migration/crossplane/gcp/reconcile/serviceaccountpolicy", reconcileHandlerFunc)
	httpmock.RegisterResponder(http.MethodPatch, "/api/dedicated/v1/migration/crossplane/gcp/reconcile/serviceaccount", reconcileHandlerFunc)
	httpmock.RegisterResponder(http.MethodPatch, "/api/dedicated/v1/migration/crossplane/gcp/reconcile/bucketpolicymember", reconcileHandlerFunc)
	httpmock.RegisterResponder(http.MethodPatch, "/api/dedicated/v1/migration/crossplane/gcp/reconcile/peering", reconcileHandlerFunc)
	httpmock.RegisterResponder(http.MethodPatch, "/api/dedicated/v1/migration/crossplane/gcp/reconcile/openidconnectprovider", reconcileHandlerFunc)
	httpmock.RegisterResponder(http.MethodPatch, "/api/dedicated/v1/migration/crossplane/gcp/reconcile/policy", reconcileHandlerFunc)
	httpmock.RegisterResponder(http.MethodPatch, "/api/dedicated/v1/migration/crossplane/gcp/reconcile/rolepolicyattachment", reconcileHandlerFunc)
	httpmock.RegisterResponder(http.MethodPatch, "/api/dedicated/v1/migration/crossplane/gcp/reconcile/role", reconcileHandlerFunc)

	cli := regionalservercli.NewMigrationServiceGCPClient("http://cluster-service.mock")
	{
		err := cli.ImportAddress(ctx, new(computev1beta1.Address))
		require.Nil(t, err)
	}
	{
		err := cli.ImportFirewall(ctx, new(computev1alpha1.Firewall))
		require.Nil(t, err)
	}
	{
		err := cli.ImportNetwork(ctx, new(computev1beta1.Network))
		require.Nil(t, err)
	}
	{
		err := cli.ImportRouter(ctx, new(computev1alpha1.Router))
		require.Nil(t, err)
	}
	{
		err := cli.ImportSubnetwork(ctx, new(computev1beta1.Subnetwork))
		require.Nil(t, err)
	}
	{
		err := cli.ImportCluster(ctx, new(containerv1beta2.Cluster))
		require.Nil(t, err)
	}
	{
		err := cli.ImportNodePool(ctx, new(containerv1beta1.NodePool))
		require.Nil(t, err)
	}
	{
		err := cli.ImportProviderConfig(ctx, new(xpv1beta1.ProviderConfig))
		require.Nil(t, err)
	}
	{
		err := cli.ImportServiceAccountKey(ctx, new(gcpiamv1alpha1.ServiceAccountKey))
		require.Nil(t, err)
	}
	{
		err := cli.ImportServiceAccountPolicy(ctx, new(gcpiamv1alpha1.ServiceAccountPolicy))
		require.Nil(t, err)
	}
	{
		err := cli.ImportServiceAccount(ctx, new(gcpiamv1alpha1.ServiceAccount))
		require.Nil(t, err)
	}
	{
		err := cli.ImportBucketPolicyMember(ctx, new(storagev1alpha1.BucketPolicyMember))
		require.Nil(t, err)
	}
	{
		err := cli.ImportPeering(ctx, new(vpcpeeringv1beta1.Peering))
		require.Nil(t, err)
	}
	{
		err := cli.ImportOIDCProvider(ctx, new(awsiamv1beta1.OpenIDConnectProvider))
		require.Nil(t, err)
	}
	{
		err := cli.ImportPolicy(ctx, new(awsiamv1beta1.Policy))
		require.Nil(t, err)
	}
	{
		err := cli.ImportRolePolicyAttachment(ctx, new(awsiamv1beta1.RolePolicyAttachment))
		require.Nil(t, err)
	}
	{
		err := cli.ImportRole(ctx, new(awsiamv1beta1.Role))
		require.Nil(t, err)
	}

	key := client.ObjectKey{
		Namespace: "foo",
		Name:      "foo",
	}
	{
		err := cli.CheckAddress(ctx, key)
		require.Nil(t, err)
	}
	{
		err := cli.CheckFirewall(ctx, key)
		require.Nil(t, err)
	}
	{
		err := cli.CheckNetwork(ctx, key)
		require.Nil(t, err)
	}
	{
		err := cli.CheckRouter(ctx, key)
		require.Nil(t, err)
	}
	{
		err := cli.CheckSubnetwork(ctx, key)
		require.Nil(t, err)
	}
	{
		err := cli.CheckCluster(ctx, key)
		require.Nil(t, err)
	}
	{
		err := cli.CheckNodePool(ctx, key)
		require.Nil(t, err)
	}
	{
		err := cli.CheckServiceAccountKey(ctx, key)
		require.Nil(t, err)
	}
	{
		err := cli.CheckServiceAccountPolicy(ctx, key)
		require.Nil(t, err)
	}
	{
		err := cli.CheckServiceAccount(ctx, key)
		require.Nil(t, err)
	}
	{
		err := cli.CheckBucketPolicyMember(ctx, key)
		require.Nil(t, err)
	}
	{
		err := cli.CheckPeering(ctx, key)
		require.Nil(t, err)
	}
	{
		err := cli.CheckOIDCProvider(ctx, key)
		require.Nil(t, err)
	}
	{
		err := cli.CheckPolicy(ctx, key)
		require.Nil(t, err)
	}
	{
		err := cli.CheckRolePolicyAttachment(ctx, key)
		require.Nil(t, err)
	}
	{
		err := cli.CheckRole(ctx, key)
		require.Nil(t, err)
	}
	{
		err := cli.ReconcileAddress(ctx, key, false)
		require.Nil(t, err)
	}
	{
		err := cli.ReconcileFirewall(ctx, key, false)
		require.Nil(t, err)
	}
	{
		err := cli.ReconcileNetwork(ctx, key, false)
		require.Nil(t, err)
	}
	{
		err := cli.ReconcileRouter(ctx, key, false)
		require.Nil(t, err)
	}
	{
		err := cli.ReconcileSubnetwork(ctx, key, false)
		require.Nil(t, err)
	}
	{
		err := cli.ReconcileCluster(ctx, key, false)
		require.Nil(t, err)
	}
	{
		err := cli.ReconcileNodePool(ctx, key, false)
		require.Nil(t, err)
	}
	{
		err := cli.ReconcileServiceAccountKey(ctx, key, false)
		require.Nil(t, err)
	}
	{
		err := cli.ReconcileServiceAccountPolicy(ctx, key, false)
		require.Nil(t, err)
	}
	{
		err := cli.ReconcileServiceAccount(ctx, key, false)
		require.Nil(t, err)
	}
	{
		err := cli.ReconcileBucketPolicyMember(ctx, key, false)
		require.Nil(t, err)
	}
	{
		err := cli.ReconcilePeering(ctx, key, false)
		require.Nil(t, err)
	}
	{
		err := cli.ReconcileOIDCProvider(ctx, key, false)
		require.Nil(t, err)
	}
	{
		err := cli.ReconcilePolicy(ctx, key, false)
		require.Nil(t, err)
	}
	{
		err := cli.ReconcileRolePolicyAttachment(ctx, key, false)
		require.Nil(t, err)
	}
	{
		err := cli.ReconcileRole(ctx, key, false)
		require.Nil(t, err)
	}
}
