package main

import (
	"context"
	"fmt"
	"os"

	"github.com/pingcap/log"
	"github.com/spf13/cobra"
	"github.com/tidbcloud/dataflow-service/dataflow-agent-ng/agent/grpc"
	"github.com/tidbcloud/dataflow-service/dataflow-agent-ng/agent/http"
	"github.com/tidbcloud/dataflow-service/dataflow-agent-ng/version"
	"github.com/tidbcloud/tiinf/monitor/tilog"
	"github.com/tidbcloud/tiinf/monitor/titracing"
	"go.uber.org/zap"
)

const (
	flagEnableTLS              = "enable-tls"
	flagHttpPort               = "http-port"
	flagEnableLocalClusterCert = "enable-local-cluster-cert"
	flagClusterModel           = "cluster-model"
)

// todo: move into internal package
var rootCmd = &cobra.Command{
	Use:               "agent",
	CompletionOptions: cobra.CompletionOptions{DisableDefaultCmd: true},
	RunE:              agentMain,
	Version:           version.Info(),
}

func init() {
	rootCmd.SetVersionTemplate("{{printf \"%s\" .Version}}\n")
	rootCmd.Flags().Bool(flagEnableTLS, true, "whether enable tls, default true")
	rootCmd.Flags().Int(flagHttpPort, 0, "port for http service")
	rootCmd.Flags().Bool(flagEnableLocalClusterCert, false, "whether enable local cluster certificate, default false")
	rootCmd.Flags().String(flagClusterModel, "dedicated", "cluster model. eg: dedicated, next-gen")
}

func agentMain(cmd *cobra.Command, args []string) error {
	// init jaeger
	_, err := titracing.InitJaeger("dataflow_agent")
	if err != nil {
		tilog.Panic(context.TODO(), "failed to init jaeger", zap.Error(err))
	}

	var (
		enableTLS bool
		httpPort  int
	)

	flags := cmd.Flags()

	enableTLS, err = flags.GetBool(flagEnableTLS)
	if err != nil {
		return err
	}
	if !flags.Changed(flagHttpPort) {
		if enableTLS {
			httpPort = 443
		} else {
			httpPort = 80
		}
	} else {
		httpPort, err = flags.GetInt(flagHttpPort)
		if err != nil {
			return err
		}
	}
	version.LogInfo()

	enableLocalClusterCert, err := flags.GetBool(flagEnableLocalClusterCert)
	if err != nil {
		return err
	}
	clusterModel, err := flags.GetString(flagClusterModel)
	if err != nil {
		return err
	}
	errCH := make(chan error, 1)
	go func() {
		log.L().Info("gonna start grpc server")
		errCH <- grpc.StartGRPCServer(enableLocalClusterCert, clusterModel)
	}()
	go func() {
		log.L().Info("gonna start http server")
		errCH <- http.StartHttpServer(httpPort, enableTLS)
	}()
	err = <-errCH
	if err != nil {
		log.Fatal("failed start agent server", zap.Error(err))
	}
	return err
}

func main() {
	if err := rootCmd.Execute(); err != nil {
		fmt.Println(err)
		os.Exit(1)
	}
}
