package commands

import (
	"fmt"
	"os"
	"os/exec"

	"github.com/contiamo/dev/cli/config"
	"github.com/spf13/cobra"
)

func init() {
	pullCmd.Flags().BoolP("update-git-repo", "g", false, "update the localdev project using git pull")
}

var pullCmd = &cobra.Command{
	Use: "pull",
	Aliases: []string{
		"update",
	},
	Example: `
	localdev pull
	localdev pull pantheon
	localdev pull pantheon hub ui
	`,
	Short: "pull the latest docker images for localdev and check if the locadev repo is up-to-date",
	ValidArgsFunction: func(cmd *cobra.Command, args []string, toComplete string) ([]string, cobra.ShellCompDirective) {
		services, err := listServices(cmd, true)
		if err != nil {
			return nil, cobra.ShellCompDirectiveError
		}
		return services, cobra.ShellCompDirectiveDefault
	},
	RunE: func(cmd *cobra.Command, args []string) error {
		updateGit, err := cmd.Flags().GetBool("update-git-repo")
		if err != nil {
			return err
		}

		pullArgs := []string{
			"-f", "docker-compose.yml",
			"-f", "docker-compose-extra.yml",
			"pull",
		}
		if len(args) > 0 {
			pullArgs = append(pullArgs, args...)
		}

		pull := exec.CommandContext(
			cmd.Context(),
			"docker-compose",
			pullArgs...,
		)
		pull.Dir = config.LocaldevRoot()
		pull.Stderr = cmd.OutOrStderr()
		pull.Stdout = cmd.OutOrStdout()
		pull.Env = os.Environ()

		err = pull.Run()
		if err != nil {
			return err
		}

		fmt.Fprintln(cmd.OutOrStdout(), "Successfully pulled images. Checking that git here is up to date...")

		fetch := exec.CommandContext(
			cmd.Context(),
			"git",
			"fetch",
		)
		fetch.Dir = config.LocaldevRoot()
		fetch.Stderr = cmd.OutOrStderr()
		fetch.Stdout = cmd.OutOrStdout()
		fetch.Env = os.Environ()

		err = fetch.Run()
		if err != nil {
			return err
		}

		updateable := exec.CommandContext(
			cmd.Context(),
			"git",
			"merge-base", "--is-ancestor", "origin/master", "HEAD",
		)
		updateable.Dir = config.LocaldevRoot()
		updateable.Stderr = nil
		updateable.Stdout = nil

		err = updateable.Run()
		if err != nil && !updateGit {
			fmt.Fprintln(cmd.OutOrStdout(), "⚠️  You are not up to date with remote master. Consider running git pull.")
			return nil
		}

		if err != nil && updateGit {
			fmt.Fprintln(cmd.OutOrStdout(), "Updating your local dev repo")
			gitUpdate := exec.CommandContext(
				cmd.Context(),
				"git",
				"pull", "-r", "origin/master",
			)
			gitUpdate.Dir = config.LocaldevRoot()
			gitUpdate.Stderr = cmd.OutOrStderr()
			gitUpdate.Stdout = cmd.OutOrStdout()
			return gitUpdate.Run()
		}

		fmt.Fprintln(cmd.OutOrStdout(), "Up to date.")
		return nil
	},
}
