package prometheus

import (
	"context"
	"errors"
	"fmt"
	"os"

	"github.com/fatih/color"
	"github.com/k8sgpt-ai/k8sgpt/pkg/common"
	"github.com/k8sgpt-ai/k8sgpt/pkg/kubernetes"
	"github.com/spf13/viper"
)

const (
	ConfigValidate = "PrometheusConfigValidate"
	ConfigRelabel  = "PrometheusConfigRelabelReport"
)

type Prometheus struct {
}

func NewPrometheus() *Prometheus {
	return &Prometheus{}
}

func (p *Prometheus) Deploy(namespace string) error {
	// no-op
	color.Green("Activating prometheus integration...")
	// TODO(pintohutch): add timeout or inherit an upstream context
	// for better signal management.
	ctx := context.Background()
	kubecontext := viper.GetString("kubecontext")
	kubeconfig := viper.GetString("kubeconfig")
	client, err := kubernetes.NewClient(kubecontext, kubeconfig)
	if err != nil {
		color.Red("Error initialising kubernetes client: %v", err)
		os.Exit(1)
	}

	// We just care about existing deployments.
	// Try and find Prometheus configurations in the cluster using the provided namespace.
	//
	// Note: We could cache this state and inject it into the various analyzers
	// to save additional parsing later.
	// However, the state of the cluster can change from activation to analysis,
	// so we would want to run this again on each analyze call anyway.
	//
	// One consequence of this is one can run `activate` in one namespace
	// and run `analyze` in another, without issues, as long as Prometheus
	// is found in both.
	// We accept this as a trade-off for the time-being to avoid having the tool
	// manage Prometheus on the behalf of users.
	podConfigs, err := findPrometheusPodConfigs(ctx, client.GetClient(), namespace)
	if err != nil {
		color.Red("Error discovering Prometheus workloads: %v", err)
		os.Exit(1)
	}
	if len(podConfigs) == 0 {
		color.Yellow(fmt.Sprintf(`Prometheus installation not found in namespace: %s.
		Please ensure Prometheus is deployed to analyze.`, namespace))
		return errors.New("no prometheus installation found")
	}
	// Prime state of the analyzer so
	color.Green("Found existing installation")
	return nil
}

func (p *Prometheus) UnDeploy(_ string) error {
	// no-op
	// We just care about existing deployments.
	color.Yellow("Integration will leave Prometheus resources deployed. This is an effective no-op in the cluster.")
	return nil
}

func (p *Prometheus) AddAnalyzer(mergedMap *map[string]common.IAnalyzer) {
	(*mergedMap)[ConfigValidate] = &ConfigAnalyzer{}
	(*mergedMap)[ConfigRelabel] = &RelabelAnalyzer{}
}

func (p *Prometheus) GetAnalyzerName() []string {
	return []string{ConfigValidate, ConfigRelabel}
}

func (p *Prometheus) GetNamespace() (string, error) {
	return "", nil
}

func (p *Prometheus) OwnsAnalyzer(analyzer string) bool {
	return (analyzer == ConfigValidate) || (analyzer == ConfigRelabel)
}

func (t *Prometheus) IsActivate() bool {
	activeFilters := viper.GetStringSlice("active_filters")

	for _, filter := range t.GetAnalyzerName() {
		for _, af := range activeFilters {
			if af == filter {
				return true
			}
		}
	}

	return false
}
