package eks

import (
	"context"
	"strings"

	"github.com/crossplane-contrib/provider-aws/apis/ec2/v1alpha1"
	xpv1 "github.com/crossplane/crossplane-runtime/apis/common/v1"
	"github.com/crossplane/crossplane-runtime/pkg/reconciler/managed"
	"github.com/pingcap/errors"
	"sigs.k8s.io/controller-runtime/pkg/client"
	"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"

	eksv1alpha1 "github.com/tidbcloud/eks-provider/api/v1alpha1"
	"github.com/tidbcloud/eks-provider/controllers/network/task"
	"github.com/tidbcloud/infra-provider/pkg/deploy"
)

type VpcEndpointCleanup struct {
	*task.BaseTask
}

func NewVpcEndpointCleanup(ctx *task.Context) *VpcEndpointCleanup {
	return &VpcEndpointCleanup{BaseTask: &task.BaseTask{Context: ctx}}
}

var _ deploy.Task = &VpcEndpointCleanup{}

func (t *VpcEndpointCleanup) Name() string {
	return "VpcEndpointCleanup"
}

func (t *VpcEndpointCleanup) Delete(ctx context.Context) deploy.Result {
	// To avoid wrong deletion, the migrated network will skip deleting the vpc endpoint.
	if eksv1alpha1.IsMigrate(t.Network) {
		return deploy.Done()
	}

	// Delete all VPC endpoints, including the s3 gateway endpoint and interface endpoints.
	// A VPC endpoint costs $7.3 per month, hibernation needs to delete all VPC endpoints.
	// Need to ensure that it will be recreate when network wakes up
	if err := deleteAllVPCEndpoints(ctx, t.Local, t.EKSNetworkSpec.VpcId); err != nil {
		return deploy.Error(err)
	}

	return deploy.Done()
}

func (t *VpcEndpointCleanup) PostDelete(ctx context.Context) deploy.Result {
	if eksv1alpha1.IsMigrate(t.Network) {
		return deploy.Done()
	}
	var endpointList v1alpha1.VPCEndpointList
	if err := t.Local.List(ctx, &endpointList, client.MatchingFields(map[string]string{
		"spec.forProvider.vpcId": t.EKSNetworkSpec.VpcId,
	})); err != nil {
		return deploy.Error(err)
	}
	cleanered := true
	// this is a workaround for the issue that the vpcendpoint cr is not deleted successfully.
	// The issue is caused by the vpc endpoint resource is deleted successfully, but crossplane cr is not deleted and reconscile failed.
	// the reconscile error message is "InvalidVpcEndpointId.NotFound: The VpcEndpoint ID 'vpce-0b1b3b3b3b3b3b3b3' does not exist"
	// In this case, we need to remove the finalizer from the endpoint and delete it manually.
	// this issue is caused by the issue in the crossplane aws provider.
	// TODO: remove this workaround after the issue is fixed.
	for _, endpoint := range endpointList.Items {
		cleanered = false
		condition := endpoint.Status.GetCondition(xpv1.TypeSynced)
		if strings.Contains(condition.Message, "InvalidVpcEndpointId.NotFound") {
			t.Logger.Info("vpc endpoint id not found, remove finalizer from the vpc endpoint")
			controllerutil.RemoveFinalizer(&endpoint, managed.FinalizerName)
			if err := t.Local.Update(ctx, &endpoint); err != nil {
				return deploy.Error(errors.Annotate(err, "failed to remove finalizer from vpc  endpoint"))
			}
		}
	}
	if cleanered {
		return deploy.Done()
	}
	return deploy.Error(errors.New("vpc endpoint is not all deleted"))
}
