package catalogue

import (
	"fmt"
	"os"
	"path"
	"strings"

	"coopcloud.tech/abra/pkg/config"
	gitPkg "coopcloud.tech/abra/pkg/git"
	"coopcloud.tech/abra/pkg/log"
	"github.com/go-git/go-git/v5"
)

// EnsureCatalogue ensures that the catalogue is cloned locally & present.
func EnsureCatalogue() error {
	catalogueDir := path.Join(config.ABRA_DIR, "catalogue")
	if _, err := os.Stat(catalogueDir); err != nil && os.IsNotExist(err) {
		log.Warnf("local recipe catalogue is missing, retrieving now")
		url := fmt.Sprintf("%s/%s.git", config.REPOS_BASE_URL, config.CATALOGUE_JSON_REPO_NAME)
		if err := gitPkg.Clone(catalogueDir, url); err != nil {
			return err
		}

		log.Debugf("cloned catalogue repository to %s", catalogueDir)
	}

	return nil
}

// EnsureIsClean makes sure that the catalogue has no unstaged changes.
func EnsureIsClean() error {
	isClean, err := gitPkg.IsClean(config.CATALOGUE_DIR)
	if err != nil {
		return err
	}

	if !isClean {
		msg := "%s has locally unstaged changes? please commit/remove your changes before proceeding"
		return fmt.Errorf(msg, config.CATALOGUE_DIR)
	}

	return nil
}

// EnsureUpToDate ensures that the local catalogue is up to date.
func EnsureUpToDate() error {
	repo, err := git.PlainOpen(config.CATALOGUE_DIR)
	if err != nil {
		return err
	}

	remotes, err := repo.Remotes()
	if err != nil {
		return err
	}

	if len(remotes) == 0 {
		msg := "cannot ensure %s is up-to-date, no git remotes configured"
		log.Debugf(msg, config.CATALOGUE_DIR)
		return nil
	}

	worktree, err := repo.Worktree()
	if err != nil {
		return err
	}

	branch, err := gitPkg.CheckoutDefaultBranch(repo, config.CATALOGUE_DIR)
	if err != nil {
		return err
	}

	opts := &git.PullOptions{
		Force:         true,
		ReferenceName: branch,
	}

	if err := worktree.Pull(opts); err != nil {
		if !strings.Contains(err.Error(), "already up-to-date") {
			return err
		}
	}

	log.Debugf("fetched latest git changes for %s", config.CATALOGUE_DIR)

	return nil
}
