package recipe

import (
	"bytes"
	"fmt"
	"os"
	"path"
	"strings"
	"text/template"

	"coopcloud.tech/abra/pkg/autocomplete"
	"coopcloud.tech/abra/pkg/config"
	"coopcloud.tech/abra/pkg/git"
	"coopcloud.tech/abra/pkg/i18n"
	"coopcloud.tech/abra/pkg/log"
	"coopcloud.tech/abra/pkg/recipe"
	"github.com/spf13/cobra"
)

// recipeMetadata is the recipe metadata for the README.md
type recipeMetadata struct {
	Name        string
	Description string
	Category    string
	Status      string
	Image       string
	Healthcheck string
	Backups     string
	Email       string
	Tests       string
	SSO         string
}

// translators: `abra recipe new` aliases. use a comma separated list of
// aliases with no spaces in between
var recipeNewAliases = i18n.G("n")

var RecipeNewCommand = &cobra.Command{
	// translators: `recipe new` command
	Use:     i18n.G("new <recipe> [flags]"),
	Aliases: strings.Split(recipeNewAliases, ","),
	// translators: Short description for `abra recipe new` command
	Short: i18n.G("Create a new recipe"),
	Long:  i18n.G(`A community managed recipe template is used.`),
	Args:  cobra.ExactArgs(1),
	ValidArgsFunction: func(
		cmd *cobra.Command,
		args []string,
		toComplete string) ([]string, cobra.ShellCompDirective) {
		return autocomplete.RecipeNameComplete()
	},
	Run: func(cmd *cobra.Command, args []string) {
		recipeName := args[0]

		r := recipe.Get(recipeName)
		if _, err := os.Stat(r.Dir); !os.IsNotExist(err) {
			log.Fatal(i18n.G("%s recipe directory already exists?", r.Dir))
		}

		url := i18n.G("%s/example.git", config.REPOS_BASE_URL)
		if err := git.Clone(r.Dir, url); err != nil {
			log.Fatal(err)
		}

		gitRepo := path.Join(r.Dir, ".git")
		if err := os.RemoveAll(gitRepo); err != nil {
			log.Fatal(err)
		}
		log.Debug(i18n.G("removed .git repo in %s", gitRepo))

		meta := newRecipeMeta(recipeName)

		for _, path := range []string{r.ReadmePath, r.SampleEnvPath} {
			tpl, err := template.ParseFiles(path)
			if err != nil {
				log.Fatal(err)
			}

			var templated bytes.Buffer
			if err := tpl.Execute(&templated, meta); err != nil {
				log.Fatal(err)
			}

			if err := os.WriteFile(path, templated.Bytes(), 0o644); err != nil {
				log.Fatal(err)
			}
		}

		if err := git.Init(r.Dir, true, gitName, gitEmail); err != nil {
			log.Fatal(err)
		}

		log.Info(i18n.G("new recipe '%s' created: %s", recipeName, path.Join(r.Dir)))
		log.Info(i18n.G("happy hacking 🎉"))
	},
}

// newRecipeMeta creates a new recipeMetadata instance with defaults
func newRecipeMeta(recipeName string) recipeMetadata {
	return recipeMetadata{
		Name:        recipeName,
		Description: "> One line description of the recipe",
		Category:    "Apps",
		Status:      "0",
		Image:       fmt.Sprintf("[`%s`](https://hub.docker.com/r/%s), 4, upstream", recipeName, recipeName),
		Healthcheck: "No",
		Backups:     "No",
		Email:       "No",
		Tests:       "No",
		SSO:         "No",
	}
}

var (
	gitName  string
	gitEmail string
)

func init() {
	RecipeNewCommand.Flags().StringVarP(
		&gitName,
		i18n.G("git-name"),
		i18n.G("N"),
		"",
		i18n.G("Git (user) name to do commits with"),
	)

	RecipeNewCommand.Flags().StringVarP(
		&gitEmail,
		i18n.G("git-email"),
		i18n.G("e"),
		"",
		i18n.G("Git email name to do commits with"),
	)
}
