package eks

import (
	"context"
	"fmt"
	"strings"

	"github.com/crossplane-contrib/provider-aws/apis/ec2/v1alpha1"
	"github.com/crossplane-contrib/provider-aws/apis/ec2/v1beta1"
	eksv1beta1 "github.com/crossplane-contrib/provider-aws/apis/eks/v1beta1"
	"sigs.k8s.io/controller-runtime/pkg/client"

	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/apimachinery/pkg/types"

	apierrors "k8s.io/apimachinery/pkg/api/errors"

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

type NatGatewayCleanup struct {
	*task.BaseTask
}

func NewNatGatewayCleanup(ctx *task.Context) *NatGatewayCleanup {
	return &NatGatewayCleanup{BaseTask: &task.BaseTask{Context: ctx}}
}

var _ deploy.Task = &NatGatewayCleanup{}

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

func (t *NatGatewayCleanup) gardenerArchNetworkIsHibernated(ctx context.Context, newNetwork *cloudv1.Network) bool {
	var oldNetwork cloudv1.Network
	err := t.Local.Get(ctx, client.ObjectKey{
		Namespace: newNetwork.Namespace,
		Name:      strings.ReplaceAll(newNetwork.Name, "eks", "aws"),
	}, &oldNetwork)
	if err != nil {
		return false
	}
	if oldNetwork.Status.Phase == cloudv1.NetworkPhaseHibernated {
		return true
	}
	return false
}

func (t *NatGatewayCleanup) Delete(ctx context.Context) deploy.Result {
	// If network is migrated, Nat gateway will shared with gardener network.
	if eksv1alpha1.IsMigrate(t.Network) {
		// If gardener arch network is not hibernated, skip delete nats, otherwise nats will deleted.
		if !t.gardenerArchNetworkIsHibernated(ctx, t.Network) {
			return deploy.Done()
		}
	}

	key := types.NamespacedName{
		Name: namer.LegacyBuildClusterNameByNetwork(t.Network),
	}
	var c eksv1beta1.Cluster
	err := t.Local.Get(ctx, key, &c)
	if !apierrors.IsNotFound(err) {
		return deploy.Error(fmt.Errorf("Wait eks cluster deleted"))
	}

	name := namer.UniqueIdentifier(t.Network.ObjectMeta)

	zones, err := t.Config.FindRegionZones(t.Network.Spec.Region)
	if err != nil {
		return deploy.Panic(err)
	}

	for i := 0; i < len(zones); i++ {
		zone := zones[i]

		re := &v1alpha1.Route{
			ObjectMeta: metav1.ObjectMeta{
				Name: namer.PrivateSubnetName(name, zone),
			},
		}
		err = k8s.DeleteObjectCompleted(ctx, t.Local, re)
		if err != nil {
			return deploy.Error(err)
		}

		nat := &v1beta1.NATGateway{
			ObjectMeta: metav1.ObjectMeta{
				Name: namer.PublicSubnetName(name, zone),
			},
		}
		err = k8s.DeleteObjectCompleted(ctx, t.Local, nat)
		if err != nil {
			return deploy.Error(err)
		}
	}

	return deploy.Done()
}
