package task

import (
	"context"

	xpv1 "github.com/crossplane/crossplane-runtime/apis/common/v1"
	"github.com/crossplane/provider-aws/apis/eks/manualv1alpha1"
	"github.com/gogo/protobuf/proto"
	"github.com/tidbcloud/eks-provider/pkg/consts"
	"github.com/tidbcloud/eks-provider/pkg/deploy"
	"github.com/tidbcloud/eks-provider/pkg/util"

	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"sigs.k8s.io/controller-runtime/pkg/controller/controllerutil"
)

type Nodegroup struct {
	*BaseTask
}

func NewNodegroup(ctx *Context) *Nodegroup {
	return &Nodegroup{BaseTask: &BaseTask{Context: ctx}}
}

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

func (t *Nodegroup) Create(ctx context.Context) deploy.Result {
	if t.cluster == nil {
		return deploy.Skip("empty cluster")
	}
	ng := manualv1alpha1.NodeGroup{
		TypeMeta: metav1.TypeMeta{
			APIVersion: "eks.aws.crossplane.io/v1alpha1",
			Kind:       "NodeGroup",
		},
		ObjectMeta: metav1.ObjectMeta{
			Name: "tidbcloud-admin-" + t.Network.Name,
		},
	}

	mut := func() error {
		ng.Spec = manualv1alpha1.NodeGroupSpec{
			ForProvider: manualv1alpha1.NodeGroupParameters{
				ClusterName:   t.cluster.Name,
				Region:        t.Network.Spec.Region,
				InstanceTypes: []string{"t3.medium"},
				ScalingConfig: &manualv1alpha1.NodeGroupScalingConfig{
					DesiredSize: proto.Int(1),
					MaxSize:     proto.Int(1),
					MinSize:     proto.Int(1),
				},
				NodeRole: t.NetworkSpec.NodeRoleArn,
				Subnets:  t.NetworkSpec.SubnetIds,
				// TODO(tangent): Replace with consts once we've finalized the labels/node selector values.
				Labels: map[string]string{"tidbcloud.com/component": "shared"},
				Tags:   map[string]string{consts.CrossplaneVendorKey: consts.CrossplaneVendorValue},
			},
			ResourceSpec: xpv1.ResourceSpec{
				ProviderConfigReference: &xpv1.Reference{Name: util.UniqueName(t.Network.Namespace, t.Network.Name)},
			},
		}
		return nil
	}
	_, err := controllerutil.CreateOrUpdate(ctx, t.Local, &ng, mut)
	return deploy.FromError(err)
}

func (t *Nodegroup) PostCreate(ctx context.Context) deploy.Result {
	return deploy.FromError(nil)
}

func (t *Nodegroup) Delete(ctx context.Context) deploy.Result {
	return deploy.FromError(nil)
}

func (t *Nodegroup) PostDelete(ctx context.Context) deploy.Result {
	return deploy.FromError(nil)
}
