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

import (
	"context"
	"fmt"
	"os"
	"strings"

	"git.unistack.org/unistack-org/pkgdash/internal/modules"
	"github.com/spf13/cobra"
	"go.unistack.org/micro/v4/logger"
	"golang.org/x/mod/modfile"
	"golang.org/x/mod/semver"
)

// checkupdateCmd represents the checkupdate command
var checkupdateCmd = NewCheckUpdateCommand()

var mvs = make(map[string]modules.Update)

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

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

	cmd := &cobra.Command{
		Use:   "checkupdate",
		Short: "CheckUpdate collects a list of dependencies with the latest updates.",
		Long:  `CheckUpdate collects a list of dependencies with the latest updates.`,
		RunE: func(cmd *cobra.Command, args []string) error {
			fmt.Println("checkupdate called")
			path := "."
			if len(os.Args) > 1 {
				path = os.Args[1]
			}

			name, err := modules.FindModFile(path)
			if err != nil {
				panic(err)
			}
			buf, err := os.ReadFile(name)
			if err != nil {
				panic(err)
			}
			mfile, err := modfile.Parse(name, buf, nil)
			if err != nil {
				panic(err)
			}

			mvs = make(map[string]modules.Update)

			updateOptions := modules.UpdateOptions{
				Pre:     cfg.UpdateOpt.Pre,
				Major:   cfg.UpdateOpt.Major,
				UpMajor: cfg.UpdateOpt.UpMajor,
				Cached:  cfg.UpdateOpt.Cached,
				OnUpdate: func(u modules.Update) {
					var modpath string // new mod path with major
					if u.Err != nil {
						logger.Error(ctx, fmt.Sprintf("%s: failed: %v", u.Module.Path, u.Err))
						return
					}
					modpath = u.Module.Path
					v := semver.Major(u.Version)
					p := modules.ModPrefix(modpath)
					if !strings.HasPrefix(u.Module.Version, v) && v != "v1" && v != "v0" {
						switch strings.HasPrefix(u.Module.Path, "gopkg.in") {
						case true:
							modpath = p + "." + v
						case false:
							modpath = p + "/" + v
						}
					}
					mvs[modpath] = u
				},
			}

			for _, req := range mfile.Require {
				updateOptions.Modules = append(updateOptions.Modules, req.Mod)
			}

			modules.Updates(updateOptions)
			logger.Info(ctx, fmt.Sprintf("Modules get update: /n %s", mvs))
			return nil
		},
	}

	return cmd
}
