package task

import (
	"context"
	"time"

	"github.com/go-logr/logr"
	"sigs.k8s.io/controller-runtime/pkg/client"

	"github.com/tidbcloud/infra-provider/pkg/deploy"
	"github.com/tidbcloud/infra-provider/regional-server/api/v1alpha1"
	"github.com/tidbcloud/infra-provider/regional-server/pkg/common/ec2client"
)

type Context struct {
	// common fields
	Local     client.Client
	EC2Client ec2client.Client // only used in aws task
	Logger    logr.Logger
	BeginAt   *time.Time

	// biz related fields
	ProviderType string // this value is assigned by vpc.spec.provider

	// all data needed to create vpc peering can be extracted from the vpcpeering and vpc CR.
	VPCPeering *v1alpha1.VPCPeering // the vpcpeering CR
	// the source vpc CR with latest status, which pointed by `vpcpeering.spec.source`
	// will be set by Gardian.Create() and only be used in task's create steps.
	VPC *v1alpha1.VPC

	// the internet CR will be set by Gardian.Create() and only be used in task's create steps.
	Internet *v1alpha1.Internet

	// will be check in Gardian.Create() and only be used in task's create steps.
	// SourceAccountID string
}

func (c *Context) ProviderConfigName() string {
	if c.VPCPeering.Spec.AccountRef != nil {
		return c.VPCPeering.Spec.AccountRef.ProviderConfigName
	}
	return ""
}

func (c *Context) Default() (*Context, error) {
	if c.VPCPeering.GetLabels() == nil {
		c.VPCPeering.Labels = map[string]string{}
	}
	if c.VPCPeering.GetAnnotations() == nil {
		c.VPCPeering.Annotations = map[string]string{}
	}
	if !c.VPCPeering.DeletionTimestamp.IsZero() {
		c.VPCPeering.Status.Phase = v1alpha1.VPCPeeringPhaseDeleting
	} else if c.VPCPeering.Status.Phase == "" {
		c.VPCPeering.Status.Phase = v1alpha1.VPCPeeringPhaseCreating
	}
	return c, nil
}

var _ deploy.Task = &BaseTask{}

type BaseTask struct {
	*Context
}

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

func (t *BaseTask) Category() deploy.TaskCategory {
	return deploy.ClusterTask
}

func (t *BaseTask) Create(ctx context.Context) deploy.Result {
	return deploy.Done()
}

func (t *BaseTask) PostCreate(ctx context.Context) deploy.Result {
	return deploy.Done()
}

func (t *BaseTask) Delete(ctx context.Context) deploy.Result {
	return deploy.Done()
}

func (t *BaseTask) PostDelete(ctx context.Context) deploy.Result {
	return deploy.Done()
}

func (t *BaseTask) MetricsStartTime() *time.Time {
	return t.BeginAt
}
