package main

import (
	"fmt"
	"log"

	aocconfig "github.com/aws-observability/aws-otel-collector/pkg/config"
	"github.com/aws-observability/aws-otel-collector/tools/version"
	dbaasconfig "github.com/pingcap/dbaas/central/config"
	"github.com/pingcap/errors"
	"github.com/spf13/cobra"
	cmdhelper "github.com/tidbcloud/metrics/cmd"
	"github.com/tidbcloud/metrics/internal/service/pipeline"
	"go.opentelemetry.io/collector/component"
	"go.opentelemetry.io/collector/service"
)

const (
	defaultDbaasConfigPath = "/etc/dbaas/config.yaml"
)

var (
	dbaasConfigPath *string
)

// Metric push-pipeline is built upon aws-otel-collector and opentelemetry-collector.
// In main() function, logging and configuration handling keep the same as aws-otel-collector.
// It supports the same components as aws-otel-collector, plus private components for TiDB Cloud.
func main() {
	factories, err := pipeline.Components()
	if err != nil {
		log.Fatalf("failed to build components: %v", err)
	}

	info := component.BuildInfo{
		Command:     "tidb-cloud-metrics-push-pipeline",
		Description: "TiDB Cloud Metrics Push Pipeline",
		Version:     version.Version,
	}

	params := service.CollectorSettings{
		Factories: factories,
		BuildInfo: info,
	}
	if err = runInteractive(params); err != nil {
		log.Fatal(err)
	}
}

func runInteractive(params service.CollectorSettings) error {
	cmd := newCommand(params)
	err := cmd.Execute()
	if err != nil {
		return fmt.Errorf("application run finished with error: %w", err)
	}

	return nil
}

// newCommand constructs a new cobra.Command using the given settings.
func newCommand(params service.CollectorSettings) *cobra.Command {
	// Build the Command we will use that only has config/set flags.
	rootCmd := &cobra.Command{
		Use:          params.BuildInfo.Command,
		Version:      params.BuildInfo.Version,
		SilenceUsage: true,
		RunE: func(cmd *cobra.Command, args []string) error {
			// Initialize provider after flags have been set
			params.ConfigMapProvider = aocconfig.GetMapProvider()
			// Initialize the global dbaas config
			if err := dbaasconfig.InitConfig(*dbaasConfigPath); err != nil {
				return errors.Annotate(err, "Initialize configuration failed")
			}
			// Initialize the global metadb driver
			cmdhelper.InitMetadbDriver()
			col, err := service.New(params)
			if err != nil {
				return fmt.Errorf("failed to construct the application: %w", err)
			}
			return col.Run(cmd.Context())
		},
	}

	rootCmd.Flags().AddGoFlagSet(aocconfig.Flags())
	defineTiDBCloudExtraFlags(rootCmd)

	return rootCmd
}

func defineTiDBCloudExtraFlags(cmd *cobra.Command) {
	dbaasConfigPath = cmd.Flags().String("dbaas-config", defaultDbaasConfigPath, "Path to the dbaas config file")
}
