// Package cli provides the interface for the command-line.
package cli

import (
	"fmt"
	"os"
	"path"

	"coopcloud.tech/abra/cli/app"
	"coopcloud.tech/abra/cli/catalogue"
	"coopcloud.tech/abra/cli/internal"
	"coopcloud.tech/abra/cli/recipe"
	"coopcloud.tech/abra/cli/record"
	"coopcloud.tech/abra/cli/server"
	"coopcloud.tech/abra/pkg/config"
	logrusStack "github.com/Gurpartap/logrus-stack"
	"github.com/sirupsen/logrus"
	"github.com/urfave/cli/v2"
)

func newAbraApp(version, commit string) *cli.App {
	app := &cli.App{
		Name: "abra",
		Usage: `The Co-op Cloud command-line utility belt 🎩🐇
    ____                           ____ _                 _
   / ___|___         ___  _ __    / ___| | ___  _   _  __| |
  | |   / _ \ _____ / _ \| '_ \  | |   | |/ _ \| | | |/ _' |
  | |__| (_) |_____| (_) | |_) | | |___| | (_) | |_| | (_| |
   \____\___/       \___/| .__/   \____|_|\___/ \__,_|\__,_|
                         |_|

If you haven't already done so, consider setting up autocompletion for a more
convenient command-line experience. See "abra autocomplete -h" for more.
		`,
		Version: fmt.Sprintf("%s-%s", version, commit[:7]),
		Commands: []*cli.Command{
			app.AppCommand,
			server.ServerCommand,
			recipe.RecipeCommand,
			catalogue.CatalogueCommand,
			record.RecordCommand,
			UpgradeCommand,
			AutoCompleteCommand,
		},
		Flags: []cli.Flag{
			internal.VerboseFlag,
			internal.DebugFlag,
			internal.NoInputFlag,
		},
		Authors: []*cli.Author{
			// If you're looking at this and you hack on Abra and you're not listed
			// here, please do add yourself! This is a community project, let's show
			// some love
			{Name: "3wordchant"},
			{Name: "decentral1se"},
			{Name: "knoflook"},
			{Name: "roxxers"},
		},
	}

	app.EnableBashCompletion = true

	app.Before = func(c *cli.Context) error {
		if internal.Debug {
			logrus.SetLevel(logrus.DebugLevel)
			logrus.SetFormatter(&logrus.TextFormatter{})
			logrus.SetOutput(os.Stderr)
			logrus.AddHook(logrusStack.StandardHook())
		}

		paths := []string{
			config.ABRA_DIR,
			path.Join(config.ABRA_DIR, "servers"),
			path.Join(config.ABRA_DIR, "apps"),
			path.Join(config.ABRA_DIR, "vendor"),
		}

		for _, path := range paths {
			if err := os.Mkdir(path, 0644); err != nil {
				if !os.IsExist(err) {
					logrus.Fatal(err)
				}
				continue
			}
		}

		logrus.Debugf("abra version '%s', commit '%s'", version, commit)

		return nil
	}
	return app
}

// RunApp runs CLI abra app.
func RunApp(version, commit string) {
	app := newAbraApp(version, commit)

	if err := app.Run(os.Args); err != nil {
		logrus.Fatal(err)
	}
}