package root

import (
	"fmt"

	"github.com/MakeNowJust/heredoc"
	"github.com/cli/cli/v2/internal/prompter"
	"github.com/cli/cli/v2/pkg/cmdutil"
	"github.com/cli/cli/v2/pkg/extensions"
	"github.com/cli/cli/v2/pkg/iostreams"
	"github.com/spf13/cobra"
)

// NewCmdOfficialExtensionStub creates a hidden stub command for an official
// extension that has not yet been installed. When invoked, it suggests
// installing the extension and, in interactive sessions, offers to do so
// immediately. After a successful install, the extension is dispatched with
// the original arguments.
func NewCmdOfficialExtensionStub(io *iostreams.IOStreams, p prompter.Prompter, em extensions.ExtensionManager, ext *extensions.OfficialExtension) *cobra.Command {
	cmd := &cobra.Command{
		Use:     ext.Name,
		Short:   fmt.Sprintf("Install the official %s extension", ext.Name),
		Hidden:  true,
		GroupID: "extension",
		// Accept any args/flags the user may have passed so we don't get
		// cobra validation errors before reaching RunE.
		DisableFlagParsing: true,
		RunE: func(cmd *cobra.Command, args []string) error {
			return officialExtensionStubRun(io, p, em, ext)
		},
	}

	cmdutil.DisableAuthCheck(cmd)

	return cmd
}

func officialExtensionStubRun(io *iostreams.IOStreams, p prompter.Prompter, em extensions.ExtensionManager, ext *extensions.OfficialExtension) error {
	stderr := io.ErrOut

	if !io.CanPrompt() {
		fmt.Fprint(stderr, heredoc.Docf(`
			%[1]s is available as an official extension.
			To install it, run:
			  gh extension install %[2]s/%[3]s
		`, fmt.Sprintf("gh %s", ext.Name), ext.Owner, ext.Repo))
		return nil
	}

	prompt := heredoc.Docf(`
		%[1]s is available as an official extension.
		Would you like to install it now?
	`, fmt.Sprintf("gh %s", ext.Name))
	confirmed, err := p.Confirm(prompt, true)
	if err != nil {
		return err
	}
	if !confirmed {
		return nil
	}

	repo := ext.Repository()
	io.StartProgressIndicatorWithLabel(fmt.Sprintf("Installing %s/%s...", ext.Owner, ext.Repo))
	installErr := em.Install(repo, "")
	io.StopProgressIndicator()
	if installErr != nil {
		return fmt.Errorf("failed to install extension: %w", installErr)
	}

	fmt.Fprintf(stderr, "Successfully installed %s/%s\n", ext.Owner, ext.Repo)
	return nil
}
