package app

import (
	"time"

	"github.com/sirupsen/logrus"
	"github.com/urfave/cli/v2"

	"gitlab.com/gitlab-org/release-cli/internal/commands"
	"gitlab.com/gitlab-org/release-cli/internal/flags"
)

// New creates cli.App for the release CLI
func New(log logrus.FieldLogger, version string) *cli.App {
	cli.HelpFlag = &cli.BoolFlag{
		Name:    "help",
		Aliases: []string{"h"},
		Usage:   "Show help",
	}
	cli.VersionFlag = &cli.BoolFlag{
		Name:    "version",
		Aliases: []string{"v"},
		Usage:   "Print the version"}

	return &cli.App{
		Name:     "release-cli",
		Usage:    "A CLI tool that interacts with GitLab's Releases API",
		Version:  version,
		HelpName: "help",
		Description: `
CLI tool that interacts with GitLab's Releases API https://docs.gitlab.com/ee/api/releases/.

All configuration flags will default to GitLab's CI predefined environment variables (https://docs.gitlab.com/ee/ci/variables/predefined_variables.html).
To override these values, use the [GLOBAL OPTIONS].

Get started with release-cli https://gitlab.com/gitlab-org/release-cli.`,
		Before: func(context *cli.Context) error {
			debug := context.Bool(flags.Debug)
			if debug {
				log.(*logrus.Entry).Logger.SetLevel(logrus.DebugLevel)
			}
			return nil
		},
		Commands: []*cli.Command{
			commands.Create(log, newHTTPClient),
			commands.CreateFromFile(log, newHTTPClient),
			commands.Get(log, newHTTPClient),
			commands.Update(log, newHTTPClient),
		},
		CommandNotFound: func(context *cli.Context, cmd string) {
			log.Errorf("Command not found: %q", cmd)
		},
		OnUsageError: func(context *cli.Context, err error, isSubcommand bool) error {
			log.WithError(err).Error("Incorrect usage")
			return cli.ShowAppHelp(context)
		},
		Compiled: time.Now(),
		Authors: []*cli.Author{
			{
				Name:  "GitLab Inc.",
				Email: "support@gitlab.com",
			},
		},
		Flags: []cli.Flag{
			&cli.StringFlag{
				Name:     flags.ServerURL,
				Usage:    "The base URL of the GitLab instance, including protocol and port, for example https://gitlab.example.com:8080",
				Required: true,
				EnvVars:  []string{"CI_SERVER_URL"},
			},
			&cli.StringFlag{
				Name:     flags.JobToken,
				Usage:    "Job token used for authenticating with the GitLab Releases API",
				Required: false,
				EnvVars:  []string{"CI_JOB_TOKEN"},
				// ensure token is not exposed by mistake if environment variable is set https://gitlab.com/gitlab-org/release-cli/-/issues/110
				DefaultText: " ",
			},
			&cli.StringFlag{
				Name:     flags.ProjectID,
				Usage:    "The current project's unique ID; used by GitLab CI internally",
				Required: true,
				EnvVars:  []string{"CI_PROJECT_ID"},
			},
			&cli.DurationFlag{
				Name:        flags.Timeout,
				Usage:       "HTTP client's timeout in Go's duration format https://golang.org/pkg/time/#ParseDuration",
				Required:    false,
				DefaultText: "30s",
				EnvVars:     []string{"RELEASE_CLI_TIMEOUT"},
			},
			&cli.StringFlag{
				Name:     flags.PrivateToken,
				Usage:    "Private token used for authenticating with the GitLab Releases API, requires api scope https://docs.gitlab.com/ee/user/profile/personal_access_tokens.html, overrides job-token",
				Required: false,
				// ensure token is not exposed by mistake if environment variable is set https://gitlab.com/gitlab-org/release-cli/-/issues/110
				DefaultText: " ",
				EnvVars:     []string{"GITLAB_PRIVATE_TOKEN"},
			},
			&cli.StringFlag{
				Name:     flags.AdditionalCACertBundle,
				Usage:    "Configure a custom SSL CA certificate authority, can be a path to file or the content of the certificate",
				Required: false,
				EnvVars:  []string{"ADDITIONAL_CA_CERT_BUNDLE"},
			},
			&cli.BoolFlag{
				Name:     flags.InsecureHTTPS,
				Usage:    "Set to true if you want to skip the client verifying the server's certificate chain and host name",
				Required: false,
				EnvVars:  []string{"INSECURE_HTTPS"},
			},
			&cli.BoolFlag{
				Name:     flags.Debug,
				Usage:    "Set to true if you want extra debug output when running release-cli",
				Required: false,
				EnvVars:  []string{"DEBUG"},
			},
		},
	}
}
