package controllers

import (
	"fmt"
	"github.com/pkg/errors"
	"helm.sh/helm/v3/pkg/action"
	"helm.sh/helm/v3/pkg/chart/loader"
	"helm.sh/helm/v3/pkg/release"
	metav1 "k8s.io/apimachinery/pkg/apis/meta/v1"
	"k8s.io/client-go/kubernetes"
	"k8s.io/client-go/tools/clientcmd"
)

// RetrieveShootKubeConfig retrieve shoot kubeconfig from secret in gardener cluster
func RetrieveShootKubeConfig(kubeCli kubernetes.Interface, namespace string, shootName string) (clientcmd.ClientConfig, error) {
	secretName := fmt.Sprintf("%s.kubeconfig", shootName)
	secret, err := kubeCli.CoreV1().Secrets(namespace).Get(secretName, metav1.GetOptions{})
	if err != nil {
		return nil, err
	}

	data := secret.Data["kubeconfig"]
	return clientcmd.NewClientConfigFromBytes(data)
}

// HelmUpgrade will install special chart when release not found, if release exit, will trying to upgrade
func HelmUpgrade(actionConfig *action.Configuration, namespace, releaseName, chartPath string, valuas map[string]interface{}, tryRun bool) (*release.Release, error) {
	chart, err := loader.Load(chartPath)
	if err != nil {
		return nil, err
	}

	if tryRun {
		// TODO: tryRun will also access kubernetes apiserver, we need a mode just exec helm template
		return nil, nil
	}
	client := action.NewUpgrade(actionConfig)
	client.Install = true
	client.Namespace = namespace
	client.MaxHistory = 10
	client.DryRun = tryRun

	// install the chart here
	rel, err := client.Run(releaseName, chart, valuas)
	if err != nil {
		noDeployError := errors.Errorf("%q has no deployed releases", releaseName)
		if err.Error() == noDeployError.Error() {
			client := action.NewInstall(actionConfig)
			client.IsUpgrade = true
			client.ReleaseName = releaseName
			client.Namespace = FluentbitReleaseNamespace
			client.DryRun = tryRun
			return client.Run(chart, valuas)
		}
	}
	return rel, err
}
