package task

import (
	"context"

	"github.com/tidbcloud/eks-provider/pkg/config"
	"github.com/tidbcloud/eks-provider/pkg/deploy"
	"github.com/tidbcloud/eks-provider/pkg/helm"

	"helm.sh/helm/v3/pkg/chart"
	"helm.sh/helm/v3/pkg/chart/loader"

	apiextensionsv1 "k8s.io/apiextensions-apiserver/pkg/apis/apiextensions/v1"
)

const (
	certManagerNamespace = "cert-manager"
)

type CertManager struct {
	*BaseTask
	config *certManagerConfig
}

type certManagerConfig struct {
	helmChartPath string
	crdPaths      []string

	controllerImage config.ImageConfig
	webhookImage    config.ImageConfig
	cainjectorImage config.ImageConfig
}

func (c *certManagerConfig) GetNamespace() string {
	return certManagerNamespace
}

func (c *certManagerConfig) GetName() string {
	return "cert-manager"
}

func (c *certManagerConfig) ToHelmChart() (result *chart.Chart, err error) {
	return loader.Load(c.helmChartPath)
}

func (c *certManagerConfig) ToHelmValues() map[string]interface{} {
	return map[string]interface{}{
		// TODO: Since these DNS servers are Internet servers, we'll need to confirm if this will actually work
		"extraArgs": []string{"--issuer-ambient-credentials", "--dns01-recursive-nameservers=8.8.8.8:53,1.1.1.1:53"},
		"image": map[string]string{
			"repository": c.controllerImage.Repo,
			"tag":        c.controllerImage.Tag,
		},
		"webhook": map[string]interface{}{
			"image": map[string]string{
				"repository": c.webhookImage.Repo,
				"tag":        c.webhookImage.Tag,
			},
		},
		"cainjector": map[string]interface{}{
			"image": map[string]string{
				"repository": c.cainjectorImage.Repo,
				"tag":        c.cainjectorImage.Tag,
			},
		},
	}
}

func (c *certManagerConfig) GetCRDs() ([]*apiextensionsv1.CustomResourceDefinition, error) {
	var result []*apiextensionsv1.CustomResourceDefinition
	for _, path := range c.crdPaths {
		crd, err := loadCRD(path)
		if err != nil {
			return nil, err
		}
		result = append(result, crd)
	}
	return result, nil
}

func NewCertManager(ctx *Context) *CertManager {
	return &CertManager{
		BaseTask: &BaseTask{Context: ctx},
		config: &certManagerConfig{
			helmChartPath:   ctx.Config.Network.CertManager.ChartPath,
			crdPaths:        ctx.Config.Network.CertManager.CRDPaths,
			controllerImage: ctx.Config.Network.CertManager.ControllerImage,
			webhookImage:    ctx.Config.Network.CertManager.WebhookImage,
			cainjectorImage: ctx.Config.Network.CertManager.CAInjectorImage,
		},
	}
}

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

func (t *CertManager) Create(ctx context.Context) deploy.Result {
	if t.remote == nil {
		return deploy.Skip("empty remote client")
	}
	return deploy.FromError(helm.Apply(ctx, t.remote, t.config))
}

func (t *CertManager) PostCreate(ctx context.Context) deploy.Result {
	// TODO: Check Webhook status
	return deploy.FromError(nil)
}
