package cmd

import (
	"fmt"
	"os"
	"strconv"

	"github.com/tidbcloud/topsql-agent/internal/app"

	"github.com/pingcap/log"
	"github.com/spf13/cobra"
	"go.uber.org/zap"
	"go.uber.org/zap/zapcore"
)

// agentCmd represents the agent command
var agentCmd = &cobra.Command{
	Use:   "agent",
	Short: "Top SQL agent",
	Long: `An agent that can collect local tidb-server/tikv-server processes' Top SQL metrics,
	and reporting to remote persistent backend for later query.`,
	RunE: func(cmd *cobra.Command, args []string) error {
		log.Info("", zap.Strings("os.Args", os.Args))
		if debug {
			log.SetLevel(zapcore.DebugLevel)
		} else {
			log.SetLevel(zapcore.InfoLevel)
		}
		log.Debug("start topsql agent server")
		if instanceID == "" {
			return fmt.Errorf("[agent] instance-id must not be empty")
		}
		if instanceName == "" {
			return fmt.Errorf("[agent] instance-name must not be empty")
		}
		if instanceComp == "" {
			return fmt.Errorf("[agent] instance-component must not be empty")
		}

		var store app.Store
		switch storeType {
		case "memstore":
			store = app.NewMemStore()
		case "tidb":
			dsn := os.Getenv("TIDB_DSN")
			clusterID, err := strconv.ParseUint(clusterIDStr, 10, 64)
			if err != nil {
				log.Error("[agent] cannot convert cluster id to integer", zap.String("clusterId", clusterIDStr))
				return err
			}
			store, err = app.NewTiDBStore(dsn, clusterID, instanceID, instanceName, instanceComp, tlsCAPath, tlsCertPath, tlsKeyPath)
			if err != nil {
				log.Error("[agent] failed to connect to TiDB store", zap.Error(err))
				return err
			}
			if err := store.InitSchema(); err != nil {
				log.Error("[agent] initialize TiDB schema failed", zap.Error(err))
				return err
			}
		default:
			return fmt.Errorf("[agent] invalid store type: %s", storeType)
		}
		server := app.NewServer(agentAddress, store)
		server.Start()
		return nil
	},
}

func init() {
	rootCmd.AddCommand(agentCmd)
}
