/*
Copyright © 2024 NAME HERE <EMAIL ADDRESS>
*/
package cli

import (
	"context"
	"fmt"
	"os"
	"path/filepath"

	"git.unistack.org/unistack-org/pkgdash/internal/configcli"
	"git.unistack.org/unistack-org/pkgdash/internal/source"
	"git.unistack.org/unistack-org/pkgdash/internal/source/github"
	"github.com/spf13/cobra"
	yamlcodec "go.unistack.org/micro-codec-yaml/v4"
	envconfig "go.unistack.org/micro-config-env/v4"
	fileconfig "go.unistack.org/micro-config-file/v4"
	"go.unistack.org/micro/v4/config"
	"go.unistack.org/micro/v4/logger"
	"go.unistack.org/micro/v4/logger/slog"
	"go.unistack.org/micro/v4/options"
)

// initCmd represents the init command
var initCmd = NewInitCommand()

var gitsource source.SourceControl = (*github.Github)(nil)

var cfg = configcli.NewConfig()

var (
	DefaultPullRequestTitle = `Bump {{.Name}} from {{.VersionOld}} to {{.VersionNew}}`
	DefaultPullRequestBody  = `Bumps {{.Name}} from {{.VersionOld}} to {{.VersionNew}}`
)

var (
	configFiles = []string{
		"dependabot.yml",
		"pkgdashcli.yml",
		"pkgdashcli.yaml",
	}
	configDirs = []string{
		".gitea",
		".github",
		".gitlab",
	}
)

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

func NewInitCommand() *cobra.Command {
	ctx := context.Background()

	logger.DefaultLogger = slog.NewLogger()

	if err := logger.DefaultLogger.Init(logger.WithCallerSkipCount(3), logger.WithLevel(logger.DebugLevel)); err != nil {
		logger.Error(ctx, fmt.Sprintf("logger init error: %v", err))
	}

	cmd := &cobra.Command{
		Use:   "init",
		Short: "Init fills the config with data from the configuration file.",
		Long:  `Init fills the config with data from the configuration file.`,
		RunE: func(cmd *cobra.Command, args []string) error {
			logger.Info(ctx, "Init called")
			var err error

			lCfg := configcli.NewConfig()

			if err = config.Load(ctx,
				[]config.Config{
					config.NewConfig(
						config.Struct(lCfg),
					),
					envconfig.NewConfig(
						config.Struct(lCfg),
					),
				},
				config.LoadOverride(true),
			); err != nil {
				logger.Fatal(ctx, fmt.Sprintf("failed to load config: %v", err))
			}

			for _, configDir := range configDirs {
				for _, configFile := range configFiles {
					path := filepath.Join(configDir, configFile)
					if _, err = os.Stat(path); os.IsNotExist(err) {
						continue
					}

					c := fileconfig.NewConfig(
						config.AllowFail(false),
						config.Struct(lCfg),
						options.Codec(yamlcodec.NewCodec()),
						fileconfig.Path(path),
					)
					err = c.Init()
					if err != nil {
						logger.Error(ctx, fmt.Sprintf("failed to init config: %v", err))
						return err
					}
					if err = c.Load(ctx, config.LoadOverride(true)); err != nil {
						logger.Error(ctx, fmt.Sprintf("failed to load config: %v", err))
						return err
					}
				}
			}

			logger.Info(ctx, fmt.Sprintf("Load config... \n %s", cfg))

			if cfg.PullRequestBody == "" {
				cfg.PullRequestBody = DefaultPullRequestBody
			}

			if cfg.PullRequestTitle == "" {
				cfg.PullRequestTitle = DefaultPullRequestTitle
			}

			gitsource = source.NewSourceControl(*lCfg)

			logger.Info(ctx, fmt.Sprintf("Git: %s", gitsource.Name()))

			cfg = lCfg

			return nil
		},
	}

	return cmd
}
