package eks

import (
	"context"
	"time"

	"github.com/tidbcloud/infra-provider/regional-server/pkg/config"
	"github.com/tidbcloud/infra-provider/regional-server/pkg/controllers"
	"github.com/tidbcloud/infra-provider/regional-server/pkg/controllers/appbox/task"
	"github.com/tidbcloud/infra-provider/regional-server/pkg/deploy"
	"github.com/tidbcloud/infra-provider/regional-server/pkg/helm"
	"github.com/tidbcloud/infra-provider/regional-server/pkg/util"
	"k8s.io/apimachinery/pkg/types"
)

type ExternalDNS struct {
	*task.BaseTask
	config *externalDNSConfig
}

type externalDNSConfig struct {
	config.InfraComponentConfig
	zoneID string
	region string
}

func (c *externalDNSConfig) ToHelmValues() map[string]interface{} {
	values := c.InfraComponentConfig.ToHelmValues()

	if c.zoneID != "" {
		appendExtraArg(values, "zone-id-filter", c.zoneID)
	}
	if c.region != "" {
		appendEnvValue(values, "AWS_DEFAULT_REGION", c.region)
	}

	return values
}

func appendExtraArg(values map[string]interface{}, key, value string) {
	if values == nil {
		return
	}

	switch extraArgs := values["extraArgs"].(type) {
	case nil:
		values["extraArgs"] = map[string]interface{}{key: value}
	case map[string]interface{}:
		extraArgs[key] = value
	case []interface{}:
		values["extraArgs"] = append(extraArgs, "--"+key+"="+value)
	default:
		values["extraArgs"] = map[string]interface{}{key: value}
	}
}

func appendEnvValue(values map[string]interface{}, name, value string) {
	if values == nil {
		return
	}

	envEntry := map[string]interface{}{"name": name, "value": value}

	switch envs := values["env"].(type) {
	case nil:
		values["env"] = []interface{}{envEntry}
	case []interface{}:
		values["env"] = append(envs, envEntry)
	default:
		values["env"] = []interface{}{envEntry}
	}
}

func NewExternalDNS(ctx *task.Context) *ExternalDNS {
	t := &task.BaseTask{Context: ctx}

	return &ExternalDNS{
		BaseTask: t,
		config: &externalDNSConfig{
			InfraComponentConfig: ctx.InfraTmplConfig.ExternalDNS,
			zoneID:               ctx.Config.DNSProviderConfig.AwsRoute53.ZoneId,
			region:               ctx.APPBox.Spec.Region,
		},
	}
}

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

func (t *ExternalDNS) shouldSkip() bool {
	return t.config.ChartPath == ""
}

func (t *ExternalDNS) Create(ctx context.Context) deploy.Result {
	t.BeginAt = util.Pointer(time.Now())
	if t.shouldSkip() {
		return deploy.Done()
	}
	return deploy.ErrorOrDone(helm.Apply(ctx, t.Remote, t.config))
}

func (t *ExternalDNS) PostCreate(ctx context.Context) deploy.Result {
	if t.shouldSkip() {
		return deploy.Done()
	}
	return deploy.ErrorOrDone(controllers.EnsureChartDeploymentReady(ctx, t.Remote, types.NamespacedName{
		Namespace: t.config.GetNamespace(),
		Name:      t.config.GetName(),
	}))
}
