// Copyright (c) HashiCorp, Inc.
// SPDX-License-Identifier: MPL-2.0

package command

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/url"
	"os"
	"path/filepath"

	"github.com/apparentlymart/go-versions/versions"
	"github.com/hashicorp/go-getter"
	"github.com/hashicorp/terraform/internal/getproviders"
	"github.com/hashicorp/terraform/internal/httpclient"
	"github.com/hashicorp/terraform/internal/tfdiags"
)

// ProvidersMirrorCommand is a Command implementation that implements the
// "terraform providers mirror" command, which populates a directory with
// local copies of provider plugins needed by the current configuration so
// that the mirror can be used to work offline, or similar.
type ProvidersMirrorCommand struct {
	Meta
}

func (c *ProvidersMirrorCommand) Synopsis() string {
	return "Save local copies of all required provider plugins"
}

func (c *ProvidersMirrorCommand) Run(args []string) int {
	args = c.Meta.process(args)
	cmdFlags := c.Meta.defaultFlagSet("providers mirror")
	var optPlatforms FlagStringSlice
	cmdFlags.Var(&optPlatforms, "platform", "target platform")
	cmdFlags.Usage = func() { c.Ui.Error(c.Help()) }
	if err := cmdFlags.Parse(args); err != nil {
		c.Ui.Error(fmt.Sprintf("Error parsing command-line flags: %s\n", err.Error()))
		return 1
	}

	var diags tfdiags.Diagnostics

	args = cmdFlags.Args()
	if len(args) != 1 {
		diags = diags.Append(tfdiags.Sourceless(
			tfdiags.Error,
			"No output directory specified",
			"The providers mirror command requires an output directory as a command-line argument.",
		))
		c.showDiagnostics(diags)
		return 1
	}
	outputDir := args[0]

	var platforms []getproviders.Platform
	if len(optPlatforms) == 0 {
		platforms = []getproviders.Platform{getproviders.CurrentPlatform}
	} else {
		platforms = make([]getproviders.Platform, 0, len(optPlatforms))
		for _, platformStr := range optPlatforms {
			platform, err := getproviders.ParsePlatform(platformStr)
			if err != nil {
				diags = diags.Append(tfdiags.Sourceless(
					tfdiags.Error,
					"Invalid target platform",
					fmt.Sprintf("The string %q given in the -platform option is not a valid target platform: %s.", platformStr, err),
				))
				continue
			}
			platforms = append(platforms, platform)
		}
	}

	config, confDiags := c.loadConfig(".")
	diags = diags.Append(confDiags)
	reqs, moreDiags := config.ProviderRequirements()
	diags = diags.Append(moreDiags)

	// Read lock file
	lockedDeps, lockedDepsDiags := c.Meta.lockedDependencies()
	diags = diags.Append(lockedDepsDiags)

	// If we have any error diagnostics already then we won't proceed further.
	if diags.HasErrors() {
		c.showDiagnostics(diags)
		return 1
	}

	// If lock file is present, validate it against configuration
	if !lockedDeps.Empty() {
		if errs := config.VerifyDependencySelections(lockedDeps); len(errs) > 0 {
			diags = diags.Append(tfdiags.Sourceless(
				tfdiags.Error,
				"Inconsistent dependency lock file",
				fmt.Sprintf("To update the locked dependency selections to match a changed configuration, run:\n  terraform init -upgrade\n got:%v", errs),
			))
		}
	}

	// Unlike other commands, this command always consults the origin registry
	// for every provider so that it can be used to update a local mirror
	// directory without needing to first disable that local mirror
	// in the CLI configuration.
	source := getproviders.NewMemoizeSource(
		getproviders.NewRegistrySource(c.Services),
	)

	// Providers from registries always use HTTP, so we don't need the full
	// generality of go-getter but it's still handy to use the HTTP getter
	// as an easy way to download over HTTP into a file on disk.
	httpGetter := getter.HttpGetter{
		Client:                httpclient.New(),
		Netrc:                 true,
		XTerraformGetDisabled: true,
	}

	// The following logic is similar to that used by the provider installer
	// in package providercache, but different in a few ways:
	// - It produces the packed directory layout rather than the unpacked
	//   layout we require in provider cache directories.
	// - It generates JSON index files that can be read by the
	//   getproviders.HTTPMirrorSource installation method if the result were
	//   copied into the docroot of an HTTP server.
	// - It can mirror packages for potentially many different target platforms,
	//   so that we can construct a multi-platform mirror regardless of which
	//   platform we run this command on.
	// - It ignores what's already present and just always downloads everything
	//   that the configuration requires. This is a command intended to be run
	//   infrequently to update a mirror, so it doesn't need to optimize away
	//   fetches of packages that might already be present.

	ctx, cancel := c.InterruptibleContext()
	defer cancel()
	for provider, constraints := range reqs {
		if provider.IsBuiltIn() {
			c.Ui.Output(fmt.Sprintf("- Skipping %s because it is built in to Terraform CLI", provider.ForDisplay()))
			continue
		}
		constraintsStr := getproviders.VersionConstraintsString(constraints)
		c.Ui.Output(fmt.Sprintf("- Mirroring %s...", provider.ForDisplay()))
		// First we'll look for the latest version that matches the given
		// constraint, which we'll then try to mirror for each target platform.
		acceptable := versions.MeetingConstraints(constraints)
		avail, _, err := source.AvailableVersions(ctx, provider)
		candidates := avail.Filter(acceptable)
		if err == nil && len(candidates) == 0 {
			err = fmt.Errorf("no releases match the given constraints %s", constraintsStr)
		}
		if err != nil {
			diags = diags.Append(tfdiags.Sourceless(
				tfdiags.Error,
				"Provider not available",
				fmt.Sprintf("Failed to download %s from its origin registry: %s.", provider.String(), err),
			))
			continue
		}
		selected := candidates.Newest()
		if !lockedDeps.Empty() {
			selected = lockedDeps.Provider(provider).Version()
			c.Ui.Output(fmt.Sprintf("  - Selected v%s to match dependency lock file", selected.String()))
		} else if len(constraintsStr) > 0 {
			c.Ui.Output(fmt.Sprintf("  - Selected v%s to meet constraints %s", selected.String(), constraintsStr))
		} else {
			c.Ui.Output(fmt.Sprintf("  - Selected v%s with no constraints", selected.String()))
		}
		for _, platform := range platforms {
			c.Ui.Output(fmt.Sprintf("  - Downloading package for %s...", platform.String()))
			meta, err := source.PackageMeta(ctx, provider, selected, platform)
			if err != nil {
				diags = diags.Append(tfdiags.Sourceless(
					tfdiags.Error,
					"Provider release not available",
					fmt.Sprintf("Failed to download %s v%s for %s: %s.", provider.String(), selected.String(), platform.String(), err),
				))
				continue
			}
			urlStr, ok := meta.Location.(getproviders.PackageHTTPURL)
			if !ok {
				// We don't expect to get non-HTTP locations here because we're
				// using the registry source, so this seems like a bug in the
				// registry source.
				diags = diags.Append(tfdiags.Sourceless(
					tfdiags.Error,
					"Provider release not available",
					fmt.Sprintf("Failed to download %s v%s for %s: Terraform's provider registry client returned unexpected location type %T. This is a bug in Terraform.", provider.String(), selected.String(), platform.String(), meta.Location),
				))
				continue
			}
			urlObj, err := url.Parse(string(urlStr))
			if err != nil {
				// We don't expect to get non-HTTP locations here because we're
				// using the registry source, so this seems like a bug in the
				// registry source.
				diags = diags.Append(tfdiags.Sourceless(
					tfdiags.Error,
					"Invalid URL for provider release",
					fmt.Sprintf("The origin registry for %s returned an invalid URL for v%s on %s: %s.", provider.String(), selected.String(), platform.String(), err),
				))
				continue
			}
			// targetPath is the path where we ultimately want to place the
			// downloaded archive, but we'll place it initially at stagingPath
			// so we can verify its checksums and signatures before making
			// it discoverable to mirror clients. (stagingPath intentionally
			// does not follow the filesystem mirror file naming convention.)
			targetPath := meta.PackedFilePath(outputDir)
			stagingPath := filepath.Join(filepath.Dir(targetPath), "."+filepath.Base(targetPath))
			err = httpGetter.GetFile(stagingPath, urlObj)
			if err != nil {
				diags = diags.Append(tfdiags.Sourceless(
					tfdiags.Error,
					"Cannot download provider release",
					fmt.Sprintf("Failed to download %s v%s for %s: %s.", provider.String(), selected.String(), platform.String(), err),
				))
				continue
			}
			if meta.Authentication != nil {
				result, err := meta.Authentication.AuthenticatePackage(getproviders.PackageLocalArchive(stagingPath))
				if err != nil {
					diags = diags.Append(tfdiags.Sourceless(
						tfdiags.Error,
						"Invalid provider package",
						fmt.Sprintf("Failed to authenticate %s v%s for %s: %s.", provider.String(), selected.String(), platform.String(), err),
					))
					continue
				}
				c.Ui.Output(fmt.Sprintf("  - Package authenticated: %s", result))
			}
			os.Remove(targetPath) // okay if it fails because we're going to try to rename over it next anyway
			err = os.Rename(stagingPath, targetPath)
			if err != nil {
				diags = diags.Append(tfdiags.Sourceless(
					tfdiags.Error,
					"Cannot download provider release",
					fmt.Sprintf("Failed to place %s package into mirror directory: %s.", provider.String(), err),
				))
				continue
			}
		}
	}

	// Now we'll generate or update the JSON index files in the directory.
	// We do this by scanning the directory to see what is present, rather than
	// by relying on the selections we made above, because we want to still
	// include in the indices any packages that were already present and
	// not affected by the changes we just made.
	available, err := getproviders.SearchLocalDirectory(outputDir)
	if err != nil {
		diags = diags.Append(tfdiags.Sourceless(
			tfdiags.Error,
			"Failed to update indexes",
			fmt.Sprintf("Could not scan the output directory to get package metadata for the JSON indexes: %s.", err),
		))
		available = nil // the following loop will be a no-op
	}
	for provider, metas := range available {
		if len(metas) == 0 {
			continue // should never happen, but we'll be resilient
		}
		// The index files live in the same directory as the package files,
		// so to figure that out without duplicating the path-building logic
		// we'll ask the getproviders package to build an archive filename
		// for a fictitious package and then use the directory portion of it.
		indexDir := filepath.Dir(getproviders.PackedFilePathForPackage(
			outputDir, provider, versions.Unspecified, getproviders.CurrentPlatform,
		))
		indexVersions := map[string]interface{}{}
		indexArchives := map[getproviders.Version]map[string]interface{}{}
		for _, meta := range metas {
			archivePath, ok := meta.Location.(getproviders.PackageLocalArchive)
			if !ok {
				// only archive files are eligible to be included in JSON
				// indices for a network mirror.
				continue
			}
			archiveFilename := filepath.Base(string(archivePath))
			version := meta.Version
			platform := meta.TargetPlatform
			hash, err := meta.Hash()
			if err != nil {
				diags = diags.Append(tfdiags.Sourceless(
					tfdiags.Error,
					"Failed to update indexes",
					fmt.Sprintf("Failed to determine a hash value for %s v%s on %s: %s.", provider, version, platform, err),
				))
				continue
			}
			indexVersions[meta.Version.String()] = map[string]interface{}{}
			if _, ok := indexArchives[version]; !ok {
				indexArchives[version] = map[string]interface{}{}
			}
			indexArchives[version][platform.String()] = map[string]interface{}{
				"url":    archiveFilename,         // a relative URL from the index file's URL
				"hashes": []string{hash.String()}, // an array to allow for additional hash formats in future
			}
		}
		mainIndex := map[string]interface{}{
			"versions": indexVersions,
		}
		mainIndexJSON, err := json.MarshalIndent(mainIndex, "", "  ")
		if err != nil {
			// Should never happen because the input here is entirely under
			// our control.
			panic(fmt.Sprintf("failed to encode main index: %s", err))
		}
		// TODO: Ideally we would do these updates as atomic swap operations by
		// creating a new file and then renaming it over the old one, in case
		// this directory is the docroot of a live mirror. An atomic swap
		// requires platform-specific code though: os.Rename alone can't do it
		// when running on Windows as of Go 1.13. We should revisit this once
		// we're supporting network mirrors, to avoid having them briefly
		// become corrupted during updates.
		err = ioutil.WriteFile(filepath.Join(indexDir, "index.json"), mainIndexJSON, 0644)
		if err != nil {
			diags = diags.Append(tfdiags.Sourceless(
				tfdiags.Error,
				"Failed to update indexes",
				fmt.Sprintf("Failed to write an updated JSON index for %s: %s.", provider, err),
			))
		}
		for version, archiveIndex := range indexArchives {
			versionIndex := map[string]interface{}{
				"archives": archiveIndex,
			}
			versionIndexJSON, err := json.MarshalIndent(versionIndex, "", "  ")
			if err != nil {
				// Should never happen because the input here is entirely under
				// our control.
				panic(fmt.Sprintf("failed to encode version index: %s", err))
			}
			err = ioutil.WriteFile(filepath.Join(indexDir, version.String()+".json"), versionIndexJSON, 0644)
			if err != nil {
				diags = diags.Append(tfdiags.Sourceless(
					tfdiags.Error,
					"Failed to update indexes",
					fmt.Sprintf("Failed to write an updated JSON index for %s v%s: %s.", provider, version, err),
				))
			}
		}
	}

	c.showDiagnostics(diags)
	if diags.HasErrors() {
		return 1
	}
	return 0
}

func (c *ProvidersMirrorCommand) Help() string {
	return `
Usage: terraform [global options] providers mirror [options] <target-dir>

  Populates a local directory with copies of the provider plugins needed for
  the current configuration, so that the directory can be used either directly
  as a filesystem mirror or as the basis for a network mirror and thus obtain
  those providers without access to their origin registries in future.

  The mirror directory will contain JSON index files that can be published
  along with the mirrored packages on a static HTTP file server to produce
  a network mirror. Those index files will be ignored if the directory is
  used instead as a local filesystem mirror.

Options:

  -platform=os_arch  Choose which target platform to build a mirror for.
                     By default Terraform will obtain plugin packages
                     suitable for the platform where you run this command.
                     Use this flag multiple times to include packages for
                     multiple target systems.

                     Target names consist of an operating system and a CPU
                     architecture. For example, "linux_amd64" selects the
                     Linux operating system running on an AMD64 or x86_64
                     CPU. Each provider is available only for a limited
                     set of target platforms.
`
}
