// 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"
)

// Verbose stores the variable from VerboseFlag.
var Verbose bool

// VerboseFlag turns on/off verbose logging down to the INFO level.
var VerboseFlag = &cli.BoolFlag{
	Name:        "verbose",
	Aliases:     []string{"V"},
	Value:       false,
	Destination: &Verbose,
	Usage:       "Show INFO messages",
}

// Debug stores the variable from DebugFlag.
var Debug bool

// DebugFlag turns on/off verbose logging down to the DEBUG level.
var DebugFlag = &cli.BoolFlag{
	Name:        "debug",
	Aliases:     []string{"d"},
	Value:       false,
	Destination: &Debug,
	Usage:       "Show DEBUG messages",
}

func newAbraApp(version, commit string) *cli.App {
	app := &cli.App{
		Name: "abra",
		Usage: `The Co-op Cloud command-line utility belt 🎩🐇

    ____                           ____ _                 _
   / ___|___         ___  _ __    / ___| | ___  _   _  __| |
  | |   / _ \ _____ / _ \| '_ \  | |   | |/ _ \| | | |/ _' |
  | |__| (_) |_____| (_) | |_) | | |___| | (_) | |_| | (_| |
   \____\___/       \___/| .__/   \____|_|\___/ \__,_|\__,_|
                         |_|
		`,
		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{
			VerboseFlag,
			DebugFlag,
			internal.NoInputFlag,
		},
		Authors: []*cli.Author{
			{Name: "3wordchant"},
			{Name: "decentral1se"},
			{Name: "knoflook"},
			{Name: "roxxers"},
		},
	}

	app.EnableBashCompletion = true

	app.Before = func(c *cli.Context) error {
		if 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, 0755); err != nil {
				if !os.IsExist(err) {
					logrus.Fatal(err)
				}
				logrus.Debugf("'%s' already created, moving on...", path)
				continue
			}
			logrus.Debugf("'%s' is missing, creating...", path)
		}

		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)
	}
}