package task

import (
	"context"
	"fmt"
	"time"

	"github.com/go-logr/logr"
	cloudv1 "github.com/tidbcloud/infra-api/api/v1"
	"k8s.io/client-go/tools/record"
	"sigs.k8s.io/controller-runtime/pkg/client"

	cdcv1 "github.com/tidbcloud/ticdc-service-ng/api/v1"
	"github.com/tidbcloud/ticdc-service-ng/pkg/cdccluster"
	"github.com/tidbcloud/ticdc-service-ng/pkg/cloud"
	"github.com/tidbcloud/ticdc-service-ng/pkg/config"
	"github.com/tidbcloud/ticdc-service-ng/pkg/deploy"
)

const (
	Finalizer = "ticdc.cloud.pingcap.com/finalizer"
)

type Context struct {
	Recorder record.EventRecorder
	Logger   logr.Logger
	Env      string // used to tag cloud resources

	Local client.Client // controlplane k8s client
	Cdc   *cdcv1.TiCDC  // controlplane cdc CR

	Remote    client.Client // dataplane k8s client
	Namespace string        // dataplane namespace

	CloudProvider   cloud.Provider
	ClusterProvider cdccluster.Provider
	CertProvider    cloud.CertificateProvider

	Config *config.Config

	beginAt *time.Time
}

type baseTask struct {
	*Context
}

func (t *baseTask) Name() string {
	return "Base"
}

func (t *baseTask) Category() deploy.TaskCategory {
	return deploy.CDCTask
}

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()
}

// MetricsStartTime will return the `BeginAt` (nil by default). For
// Task whose metrics need to be exported, the `BeginAt` should be
// initialized when the `Create` is being called.
func (t *baseTask) MetricsStartTime() *time.Time {
	return t.beginAt
}

// name is hardcoded in tidb-operator v1, we must follow it
func (t *baseTask) getClusterCertName() string {
	component := cloudv1.ComponentTiCDC
	return fmt.Sprintf("%s-%s-cluster-secret", t.Cdc.Name, component)
}

// name is hardcoded in tidb-operator v1, we must follow it
func (t *baseTask) getClientCertName() string {
	component := "cluster"
	return fmt.Sprintf("%s-%s-client-secret", t.Cdc.Name, component)
}

func (t *baseTask) getVolumeAttributesClassName() string {
	scType := t.Cdc.Spec.Storage.Type
	scIops := t.Cdc.Spec.Storage.Iops
	scThroughput := t.Cdc.Spec.Storage.ThroughputMbs
	return fmt.Sprintf("cdc-%s-%d-%d", scType, scIops, scThroughput)
}
