package br

import (
	"context"
	"fmt"

	"github.com/mitchellh/mapstructure"
	"sigs.k8s.io/controller-runtime/pkg/client"
	"sigs.k8s.io/controller-runtime/pkg/log"

	"github.com/tidbcloud/eks-provider/controllers/provider"
	"github.com/tidbcloud/eks-provider/controllers/workflow/action"
	cloudv1 "github.com/tidbcloud/infra-api/api/v1"
	"github.com/tidbcloud/infra-provider/pkg/consts"
)

// / deleteNodePool deletes a nodepool
var _ action.Action = &deleteNodePool{}

type deleteNodePool struct {
	cli client.Client
}

type deleteNodePoolInputs struct {
	Name         string `mapstructure:"name" json:"name" validate:"required"`
	ProviderType string `mapstructure:"providerType" json:"providerType" validate:"required"`
}

func NewDeleteNodePool(cli client.Client) action.Action {
	return &deleteNodePool{cli: cli}
}

func (a *deleteNodePool) Name() cloudv1.WorkflowActionName {
	return "DeleteNodePoolAction"
}

func (a *deleteNodePool) PreCheck(ctx context.Context, wf *cloudv1.Workflow, step cloudv1.WorkflowStep) error {
	inputs := &deleteNodePoolInputs{}
	if err := mapstructure.Decode(step.Inputs.Object, inputs); err != nil {
		return fmt.Errorf("decode inputs: %w", err)
	}
	if err := validate.Struct(inputs); err != nil {
		return fmt.Errorf("validate inputs: %w", err)
	}
	return nil
}

func (a *deleteNodePool) Handle(ctx context.Context, wf *cloudv1.Workflow, step cloudv1.WorkflowStep) error {
	logger := log.FromContext(ctx)

	inputs := &deleteNodePoolInputs{}
	_ = mapstructure.Decode(step.Inputs.Object, inputs)
	var np provider.NodePoolProvider
	switch inputs.ProviderType {
	case consts.ProviderTypeAKS:
		// For deletion, we don't need providerconfig
		np = provider.NewAzureNodePool(a.cli, "")
	case consts.ProviderTypeEKS, consts.ProviderTypeGKE:
		return fmt.Errorf("nodepool provider unimplemented for %s", inputs.ProviderType)
	default:
		return fmt.Errorf("unknown provider type %s", inputs.ProviderType)
	}
	logger.Info("delete nodepool", "nodepool", inputs.Name, "provider", np.GetProviderName())
	if err := np.DeleteNodePool(ctx, inputs.Name); err != nil {
		return err
	}
	return nil
}
