package internal

import (
	"errors"
	"fmt"

	"coopcloud.tech/abra/pkg/formatter"
	"coopcloud.tech/abra/pkg/i18n"
	"coopcloud.tech/abra/pkg/log"
	"coopcloud.tech/abra/pkg/recipe"
	"github.com/AlecAivazis/survey/v2"
	"github.com/distribution/reference"
)

// PromptBumpType prompts for version bump type
func PromptBumpType(tagString, latestRelease, changeOverview string) error {
	if (!Major && !Minor && !Patch) && tagString == "" {
		fmt.Print(i18n.G(`
You need to make a decision about what kind of an update this new recipe
version is. If someone else performs this upgrade, do they have to do some
migration work or take care of some breaking changes? This can be signaled in
the version you specify on the recipe deploy label and is called a semantic
version.

The latest published version is %s.

%s

Here is a semver cheat sheet (more on https://semver.org):

    major: new features/bug fixes, backwards incompatible (e.g 1.0.0 -> 2.0.0).
           the upgrade won't work without some preparation work and others need
           to take care when performing it. "it could go wrong".

    minor: new features/bug fixes, backwards compatible (e.g. 0.1.0 -> 0.2.0).
           the upgrade should Just Work and there are no breaking changes in
           the app and the recipe config. "it should go fine".

    patch: bug fixes, backwards compatible (e.g. 0.0.1 -> 0.0.2). this upgrade
           should also Just Work and is mostly to do with minor bug fixes
           and/or security patches. "nothing to worry about".

`, latestRelease, changeOverview))

		var chosenBumpType string
		prompt := &survey.Select{
			Message: fmt.Sprintf("select recipe version increment type"),
			Options: []string{i18n.G("major"), i18n.G("minor"), i18n.G("patch")},
		}

		if err := survey.AskOne(prompt, &chosenBumpType); err != nil {
			return err
		}

		SetBumpType(chosenBumpType)
	}

	return nil
}

// GetBumpType figures out which bump type is specified
func GetBumpType() string {
	var bumpType string

	if Major {
		bumpType = i18n.G("major")
	} else if Minor {
		bumpType = i18n.G("minor")
	} else if Patch {
		bumpType = i18n.G("patch")
	} else {
		log.Fatal(i18n.G("no version bump type specififed?"))
	}

	return bumpType
}

// SetBumpType figures out which bump type is specified
func SetBumpType(bumpType string) {
	if bumpType == i18n.G("major") {
		Major = true
	} else if bumpType == i18n.G("minor") {
		Minor = true
	} else if bumpType == i18n.G("patch") {
		Patch = true
	} else {
		log.Fatal(i18n.G("no version bump type specififed?"))
	}
}

// GetMainAppImage retrieves the main 'app' image name
func GetMainAppImage(recipe recipe.Recipe) (string, error) {
	var path string

	config, err := recipe.GetComposeConfig()
	if err != nil {
		return "", err
	}

	for _, service := range config.Services {
		if service.Name == "app" {
			img, err := reference.ParseNormalizedNamed(service.Image)
			if err != nil {
				return "", err
			}

			path = reference.Path(img)
			path = formatter.StripTagMeta(path)

			return path, nil
		}
	}

	if path == "" {
		return path, errors.New(i18n.G("%s has no main 'app' service?", recipe.Name))
	}

	return path, nil
}
