package main

import (
	"context"
	"fmt"
	"os"

	"github.com/creasty/defaults"
	"github.com/go-playground/validator/v10"
	"github.com/spf13/cobra"
	"gopkg.in/yaml.v3"

	"github.com/tidbcloud/devops/pkg/infra/config"
	"github.com/tidbcloud/devops/pkg/infra/log"
)

var (
	flagConfig string
)

func newRootCmd() *cobra.Command {
	cmd := &cobra.Command{
		Use:     "jump-gateway",
		Version: "v0.0.0",
		Run:     execute,
	}

	cmd.Flags().StringVar(&flagConfig, "config", "", "path to read jump gateway config")
	_ = cmd.MarkFlagRequired("config")
	return cmd
}

func execute(cmd *cobra.Command, args []string) {
	conf, err := loadConfig(flagConfig)
	exitIfErr(err, "failed to load config")

	err = setup(conf)
	exitIfErr(err, "failed to init access logger")

	err = run(conf)
	exitIfErr(err, "jump server exited with error")
}

func loadConfig(filepath string) (*config.JumpGatewayConfig, error) {
	conf := &config.JumpGatewayConfig{}
	if err := defaults.Set(conf); err != nil {
		return nil, fmt.Errorf("failed to set default config: %w", err)
	}

	data, err := os.ReadFile(filepath)
	if err != nil {
		return nil, fmt.Errorf("failed to read config file: %w", err)
	}

	if err := yaml.Unmarshal(data, conf); err != nil {
		return nil, fmt.Errorf("failed to unmarshal config file: %w", err)
	}

	if err := validator.New().Struct(conf); err != nil {
		return nil, fmt.Errorf("failed to validate config: %w", err)
	}

	return conf, nil
}

func main() {
	cmd := newRootCmd()
	err := cmd.ExecuteContext(context.Background())
	exitIfErr(err, "failed to execute cmd")
}

func exitIfErr(err error, msg string) {
	if err != nil {
		if log.Logger.IsZero() {
			fmt.Fprintln(os.Stderr, err.Error())
		} else {
			log.Logger.Error(err, msg)
		}
		os.Exit(1)
	}
}
