package providercache

import (
	"context"
	"fmt"
	"sort"
	"strings"

	"github.com/apparentlymart/go-versions/versions"

	"github.com/hashicorp/terraform/internal/addrs"
	copydir "github.com/hashicorp/terraform/internal/copy"
	"github.com/hashicorp/terraform/internal/depsfile"
	"github.com/hashicorp/terraform/internal/getproviders"
)

// Installer is the main type in this package, representing a provider installer
// with a particular configuration-specific cache directory and an optional
// global cache directory.
type Installer struct {
	// targetDir is the cache directory we're ultimately aiming to get the
	// requested providers installed into.
	targetDir *Dir

	// source is the provider source that the installer will use to discover
	// what provider versions are available for installation and to
	// find the source locations for any versions that are not already
	// available via one of the cache directories.
	source getproviders.Source

	// globalCacheDir is an optional additional directory that will, if
	// provided, be treated as a read-through cache when retrieving new
	// provider versions. That is, new packages are fetched into this
	// directory first and then linked into targetDir, which allows sharing
	// both the disk space and the download time for a particular provider
	// version between different configurations on the same system.
	globalCacheDir *Dir

	// builtInProviderTypes is an optional set of types that should be
	// considered valid to appear in the special terraform.io/builtin/...
	// namespace, which we use for providers that are built in to Terraform
	// and thus do not need any separate installation step.
	builtInProviderTypes []string

	// unmanagedProviderTypes is a set of provider addresses that should be
	// considered implemented, but that Terraform does not manage the
	// lifecycle for, and therefore does not need to worry about the
	// installation of.
	unmanagedProviderTypes map[addrs.Provider]struct{}
}

// NewInstaller constructs and returns a new installer with the given target
// directory and provider source.
//
// A newly-created installer does not have a global cache directory configured,
// but a caller can make a follow-up call to SetGlobalCacheDir to provide
// one prior to taking any installation actions.
//
// The target directory MUST NOT also be an input consulted by the given source,
// or the result is undefined.
func NewInstaller(targetDir *Dir, source getproviders.Source) *Installer {
	return &Installer{
		targetDir: targetDir,
		source:    source,
	}
}

// Clone returns a new Installer which has the a new target directory but
// the same optional global cache directory, the same installation sources,
// and the same built-in/unmanaged providers. The result can be mutated further
// using the various setter methods without affecting the original.
func (i *Installer) Clone(targetDir *Dir) *Installer {
	// For now all of our setter methods just overwrite field values in
	// their entirety, rather than mutating things on the other side of
	// the shared pointers, and so we can safely just shallow-copy the
	// root. We might need to be more careful here if in future we add
	// methods that allow deeper mutations through the stored pointers.
	ret := *i
	ret.targetDir = targetDir
	return &ret
}

// ProviderSource returns the getproviders.Source that the installer would
// use for installing any new providers.
func (i *Installer) ProviderSource() getproviders.Source {
	return i.source
}

// SetGlobalCacheDir activates a second tier of caching for the receiving
// installer, with the given directory used as a read-through cache for
// installation operations that need to retrieve new packages.
//
// The global cache directory for an installer must never be the same as its
// target directory, and must not be used as one of its provider sources.
// If these overlap then undefined behavior will result.
func (i *Installer) SetGlobalCacheDir(cacheDir *Dir) {
	// A little safety check to catch straightforward mistakes where the
	// directories overlap. Better to panic early than to do
	// possibly-distructive actions on the cache directory downstream.
	if same, err := copydir.SameFile(i.targetDir.baseDir, cacheDir.baseDir); err == nil && same {
		panic(fmt.Sprintf("global cache directory %s must not match the installation target directory %s", cacheDir.baseDir, i.targetDir.baseDir))
	}
	i.globalCacheDir = cacheDir
}

// HasGlobalCacheDir returns true if someone has previously called
// SetGlobalCacheDir to configure a global cache directory for this installer.
func (i *Installer) HasGlobalCacheDir() bool {
	return i.globalCacheDir != nil
}

// SetBuiltInProviderTypes tells the receiver to consider the type names in the
// given slice to be valid as providers in the special special
// terraform.io/builtin/... namespace that we use for providers that are
// built in to Terraform and thus do not need a separate installation step.
//
// If a caller requests installation of a provider in that namespace, the
// installer will treat it as a no-op if its name exists in this list, but
// will produce an error if it does not.
//
// The default, if this method isn't called, is for there to be no valid
// builtin providers.
//
// Do not modify the buffer under the given slice after passing it to this
// method.
func (i *Installer) SetBuiltInProviderTypes(types []string) {
	i.builtInProviderTypes = types
}

// SetUnmanagedProviderTypes tells the receiver to consider the providers
// indicated by the passed addrs.Providers as unmanaged. Terraform does not
// need to control the lifecycle of these providers, and they are assumed to be
// running already when Terraform is started. Because these are essentially
// processes, not binaries, Terraform will not do any work to ensure presence
// or versioning of these binaries.
func (i *Installer) SetUnmanagedProviderTypes(types map[addrs.Provider]struct{}) {
	i.unmanagedProviderTypes = types
}

// EnsureProviderVersions compares the given provider requirements with what
// is already available in the installer's target directory and then takes
// appropriate installation actions to ensure that suitable packages
// are available in the target cache directory.
//
// The given mode modifies how the operation will treat providers that already
// have acceptable versions available in the target cache directory. See the
// documentation for InstallMode and the InstallMode values for more
// information.
//
// The given context can be used to cancel the overall installation operation
// (causing any operations in progress to fail with an error), and can also
// include an InstallerEvents value for optional intermediate progress
// notifications.
//
// If a given InstallerEvents subscribes to notifications about installation
// failures then those notifications will be redundant with the ones included
// in the final returned error value so callers should show either one or the
// other, and not both.
func (i *Installer) EnsureProviderVersions(ctx context.Context, locks *depsfile.Locks, reqs getproviders.Requirements, mode InstallMode) (*depsfile.Locks, error) {
	errs := map[addrs.Provider]error{}
	evts := installerEventsForContext(ctx)

	// We'll work with a copy of the given locks, so we can modify it and
	// return the updated locks without affecting the caller's object.
	// We'll add, replace, or remove locks in here during our work so that the
	// final locks file reflects what the installer has selected.
	locks = locks.DeepCopy()

	if cb := evts.PendingProviders; cb != nil {
		cb(reqs)
	}

	// Step 1: Which providers might we need to fetch a new version of?
	// This produces the subset of requirements we need to ask the provider
	// source about. If we're in the normal (non-upgrade) mode then we'll
	// just ask the source to confirm the continued existence of what
	// was locked, or otherwise we'll find the newest version matching the
	// configured version constraint.
	mightNeed := map[addrs.Provider]getproviders.VersionSet{}
	locked := map[addrs.Provider]bool{}
	for provider, versionConstraints := range reqs {
		if provider.IsBuiltIn() {
			// Built in providers do not require installation but we'll still
			// verify that the requested provider name is valid.
			valid := false
			for _, name := range i.builtInProviderTypes {
				if name == provider.Type {
					valid = true
					break
				}
			}
			var err error
			if valid {
				if len(versionConstraints) == 0 {
					// Other than reporting an event for the outcome of this
					// provider, we'll do nothing else with it: it's just
					// automatically available for use.
					if cb := evts.BuiltInProviderAvailable; cb != nil {
						cb(provider)
					}
				} else {
					// A built-in provider is not permitted to have an explicit
					// version constraint, because we can only use the version
					// that is built in to the current Terraform release.
					err = fmt.Errorf("built-in providers do not support explicit version constraints")
				}
			} else {
				err = fmt.Errorf("this Terraform release has no built-in provider named %q", provider.Type)
			}
			if err != nil {
				errs[provider] = err
				if cb := evts.BuiltInProviderFailure; cb != nil {
					cb(provider, err)
				}
			}
			continue
		}
		if _, ok := i.unmanagedProviderTypes[provider]; ok {
			// unmanaged providers do not require installation
			continue
		}
		acceptableVersions := versions.MeetingConstraints(versionConstraints)
		if !mode.forceQueryAllProviders() {
			// If we're not forcing potential changes of version then an
			// existing selection from the lock file takes priority over
			// the currently-configured version constraints.
			if lock := locks.Provider(provider); lock != nil {
				if !acceptableVersions.Has(lock.Version()) {
					err := fmt.Errorf(
						"locked provider %s %s does not match configured version constraint %s; must use terraform init -upgrade to allow selection of new versions",
						provider, lock.Version(), getproviders.VersionConstraintsString(versionConstraints),
					)
					errs[provider] = err
					// This is a funny case where we're returning an error
					// before we do any querying at all. To keep the event
					// stream consistent without introducing an extra event
					// type, we'll emit an artificial QueryPackagesBegin for
					// this provider before we indicate that it failed using
					// QueryPackagesFailure.
					if cb := evts.QueryPackagesBegin; cb != nil {
						cb(provider, versionConstraints, true)
					}
					if cb := evts.QueryPackagesFailure; cb != nil {
						cb(provider, err)
					}
					continue
				}
				acceptableVersions = versions.Only(lock.Version())
				locked[provider] = true
			}
		}
		mightNeed[provider] = acceptableVersions
	}

	// Step 2: Query the provider source for each of the providers we selected
	// in the first step and select the latest available version that is
	// in the set of acceptable versions.
	//
	// This produces a set of packages to install to our cache in the next step.
	need := map[addrs.Provider]getproviders.Version{}
NeedProvider:
	for provider, acceptableVersions := range mightNeed {
		if err := ctx.Err(); err != nil {
			// If our context has been cancelled or reached a timeout then
			// we'll abort early, because subsequent operations against
			// that context will fail immediately anyway.
			return nil, err
		}

		if cb := evts.QueryPackagesBegin; cb != nil {
			cb(provider, reqs[provider], locked[provider])
		}
		available, warnings, err := i.source.AvailableVersions(ctx, provider)
		if err != nil {
			// TODO: Consider retrying a few times for certain types of
			// source errors that seem likely to be transient.
			errs[provider] = err
			if cb := evts.QueryPackagesFailure; cb != nil {
				cb(provider, err)
			}
			// We will take no further actions for this provider.
			continue
		}
		if len(warnings) > 0 {
			if cb := evts.QueryPackagesWarning; cb != nil {
				cb(provider, warnings)
			}
		}
		available.Sort()                           // put the versions in increasing order of precedence
		for i := len(available) - 1; i >= 0; i-- { // walk backwards to consider newer versions first
			if acceptableVersions.Has(available[i]) {
				need[provider] = available[i]
				if cb := evts.QueryPackagesSuccess; cb != nil {
					cb(provider, available[i])
				}
				continue NeedProvider
			}
		}
		// If we get here then the source has no packages that meet the given
		// version constraint, which we model as a query error.
		if locked[provider] {
			// This situation should be a rare one: it suggests that a
			// version was previously available but was yanked for some
			// reason.
			lock := locks.Provider(provider)
			err = fmt.Errorf("the previously-selected version %s is no longer available", lock.Version())
		} else {
			err = fmt.Errorf("no available releases match the given constraints %s", getproviders.VersionConstraintsString(reqs[provider]))
		}
		errs[provider] = err
		if cb := evts.QueryPackagesFailure; cb != nil {
			cb(provider, err)
		}
	}

	// Step 3: For each provider version we've decided we need to install,
	// install its package into our target cache (possibly via the global cache).
	authResults := map[addrs.Provider]*getproviders.PackageAuthenticationResult{} // record auth results for all successfully fetched providers
	targetPlatform := i.targetDir.targetPlatform                                  // we inherit this to behave correctly in unit tests
	for provider, version := range need {
		if err := ctx.Err(); err != nil {
			// If our context has been cancelled or reached a timeout then
			// we'll abort early, because subsequent operations against
			// that context will fail immediately anyway.
			return nil, err
		}

		lock := locks.Provider(provider)
		var preferredHashes []getproviders.Hash
		if lock != nil && lock.Version() == version { // hash changes are expected if the version is also changing
			preferredHashes = lock.PreferredHashes()
		}

		// If our target directory already has the provider version that fulfills the lock file, carry on
		if installed := i.targetDir.ProviderVersion(provider, version); installed != nil {
			if len(preferredHashes) > 0 {
				if matches, _ := installed.MatchesAnyHash(preferredHashes); matches {
					if cb := evts.ProviderAlreadyInstalled; cb != nil {
						cb(provider, version)
					}
					continue
				}
			}
		}

		if i.globalCacheDir != nil {
			// Step 3a: If our global cache already has this version available then
			// we'll just link it in.
			if cached := i.globalCacheDir.ProviderVersion(provider, version); cached != nil {
				if cb := evts.LinkFromCacheBegin; cb != nil {
					cb(provider, version, i.globalCacheDir.baseDir)
				}
				if _, err := cached.ExecutableFile(); err != nil {
					err := fmt.Errorf("provider binary not found: %s", err)
					errs[provider] = err
					if cb := evts.LinkFromCacheFailure; cb != nil {
						cb(provider, version, err)
					}
					continue
				}

				err := i.targetDir.LinkFromOtherCache(cached, preferredHashes)
				if err != nil {
					errs[provider] = err
					if cb := evts.LinkFromCacheFailure; cb != nil {
						cb(provider, version, err)
					}
					continue
				}
				// We'll fetch what we just linked to make sure it actually
				// did show up there.
				new := i.targetDir.ProviderVersion(provider, version)
				if new == nil {
					err := fmt.Errorf("after linking %s from provider cache at %s it is still not detected in the target directory; this is a bug in Terraform", provider, i.globalCacheDir.baseDir)
					errs[provider] = err
					if cb := evts.LinkFromCacheFailure; cb != nil {
						cb(provider, version, err)
					}
					continue
				}

				// The LinkFromOtherCache call above should've verified that
				// the package matches one of the hashes previously recorded,
				// if any. We'll now augment those hashes with one freshly
				// calculated from the package we just linked, which allows
				// the lock file to gradually transition to recording newer hash
				// schemes when they become available.
				var priorHashes []getproviders.Hash
				if lock != nil && lock.Version() == version {
					// If the version we're installing is identical to the
					// one we previously locked then we'll keep all of the
					// hashes we saved previously and add to it. Otherwise
					// we'll be starting fresh, because each version has its
					// own set of packages and thus its own hashes.
					priorHashes = append(priorHashes, preferredHashes...)

					// NOTE: The behavior here is unfortunate when a particular
					// provider version was already cached on the first time
					// the current configuration requested it, because that
					// means we don't currently get the opportunity to fetch
					// and verify the checksums for the new package from
					// upstream. That's currently unavoidable because upstream
					// checksums are in the "ziphash" format and so we can't
					// verify them against our cache directory's unpacked
					// packages: we'd need to go fetch the package from the
					// origin and compare against it, which would defeat the
					// purpose of the global cache.
					//
					// If we fetch from upstream on the first encounter with
					// a particular provider then we'll end up in the other
					// codepath below where we're able to also include the
					// checksums from the origin registry.
				}
				newHash, err := cached.Hash()
				if err != nil {
					err := fmt.Errorf("after linking %s from provider cache at %s, failed to compute a checksum for it: %s", provider, i.globalCacheDir.baseDir, err)
					errs[provider] = err
					if cb := evts.LinkFromCacheFailure; cb != nil {
						cb(provider, version, err)
					}
					continue
				}
				// The hashes slice gets deduplicated in the lock file
				// implementation, so we don't worry about potentially
				// creating a duplicate here.
				var newHashes []getproviders.Hash
				newHashes = append(newHashes, priorHashes...)
				newHashes = append(newHashes, newHash)
				locks.SetProvider(provider, version, reqs[provider], newHashes)
				if cb := evts.ProvidersLockUpdated; cb != nil {
					// We want to ensure that newHash and priorHashes are
					// sorted. newHash is a single value, so it's definitely
					// sorted. priorHashes are pulled from the lock file, so
					// are also already sorted.
					cb(provider, version, []getproviders.Hash{newHash}, nil, priorHashes)
				}

				if cb := evts.LinkFromCacheSuccess; cb != nil {
					cb(provider, version, new.PackageDir)
				}
				continue // Don't need to do full install, then.
			}
		}

		// Step 3b: Get the package metadata for the selected version from our
		// provider source.
		//
		// This is the step where we might detect and report that the provider
		// isn't available for the current platform.
		if cb := evts.FetchPackageMeta; cb != nil {
			cb(provider, version)
		}
		meta, err := i.source.PackageMeta(ctx, provider, version, targetPlatform)
		if err != nil {
			errs[provider] = err
			if cb := evts.FetchPackageFailure; cb != nil {
				cb(provider, version, err)
			}
			continue
		}

		// Step 3c: Retrieve the package indicated by the metadata we received,
		// either directly into our target directory or via the global cache
		// directory.
		if cb := evts.FetchPackageBegin; cb != nil {
			cb(provider, version, meta.Location)
		}
		var installTo, linkTo *Dir
		if i.globalCacheDir != nil {
			installTo = i.globalCacheDir
			linkTo = i.targetDir
		} else {
			installTo = i.targetDir
			linkTo = nil // no linking needed
		}

		allowedHashes := preferredHashes
		if mode.forceInstallChecksums() {
			allowedHashes = []getproviders.Hash{}
		}

		authResult, err := installTo.InstallPackage(ctx, meta, allowedHashes)
		if err != nil {
			// TODO: Consider retrying for certain kinds of error that seem
			// likely to be transient. For now, we just treat all errors equally.
			errs[provider] = err
			if cb := evts.FetchPackageFailure; cb != nil {
				cb(provider, version, err)
			}
			continue
		}
		new := installTo.ProviderVersion(provider, version)
		if new == nil {
			err := fmt.Errorf("after installing %s it is still not detected in the target directory; this is a bug in Terraform", provider)
			errs[provider] = err
			if cb := evts.FetchPackageFailure; cb != nil {
				cb(provider, version, err)
			}
			continue
		}
		if _, err := new.ExecutableFile(); err != nil {
			err := fmt.Errorf("provider binary not found: %s", err)
			errs[provider] = err
			if cb := evts.FetchPackageFailure; cb != nil {
				cb(provider, version, err)
			}
			continue
		}
		if linkTo != nil {
			// We skip emitting the "LinkFromCache..." events here because
			// it's simpler for the caller to treat them as mutually exclusive.
			// We can just subsume the linking step under the "FetchPackage..."
			// series here (and that's why we use FetchPackageFailure below).
			// We also don't do a hash check here because we already did that
			// as part of the installTo.InstallPackage call above.
			err := linkTo.LinkFromOtherCache(new, nil)
			if err != nil {
				errs[provider] = err
				if cb := evts.FetchPackageFailure; cb != nil {
					cb(provider, version, err)
				}
				continue
			}
		}
		authResults[provider] = authResult

		// The InstallPackage call above should've verified that
		// the package matches one of the hashes previously recorded,
		// if any. We'll now augment those hashes with a new set populated
		// with the hashes returned by the upstream source and from the
		// package we've just installed, which allows the lock file to
		// gradually transition to newer hash schemes when they become
		// available.
		//
		// This is assuming that if a package matches both a hash we saw before
		// _and_ a new hash then the new hash is a valid substitute for
		// the previous hash.
		//
		// The hashes slice gets deduplicated in the lock file
		// implementation, so we don't worry about potentially
		// creating duplicates here.
		var priorHashes []getproviders.Hash
		if lock != nil && lock.Version() == version {
			// If the version we're installing is identical to the
			// one we previously locked then we'll keep all of the
			// hashes we saved previously and add to it. Otherwise
			// we'll be starting fresh, because each version has its
			// own set of packages and thus its own hashes.
			priorHashes = append(priorHashes, preferredHashes...)
		}
		newHash, err := new.Hash()
		if err != nil {
			err := fmt.Errorf("after installing %s, failed to compute a checksum for it: %s", provider, err)
			errs[provider] = err
			if cb := evts.FetchPackageFailure; cb != nil {
				cb(provider, version, err)
			}
			continue
		}

		var signedHashes []getproviders.Hash
		if authResult.SignedByAnyParty() {
			// We'll trust new hashes from upstream only if they were verified
			// as signed by a suitable key. Otherwise, we'd record only
			// a new hash we just calculated ourselves from the bytes on disk,
			// and so the hashes would cover only the current platform.
			signedHashes = append(signedHashes, meta.AcceptableHashes()...)
		}

		var newHashes []getproviders.Hash
		newHashes = append(newHashes, newHash)
		newHashes = append(newHashes, priorHashes...)
		newHashes = append(newHashes, signedHashes...)

		locks.SetProvider(provider, version, reqs[provider], newHashes)
		if cb := evts.ProvidersLockUpdated; cb != nil {
			// newHash and priorHashes are already sorted.
			// But we do need to sort signedHashes so we can reason about it
			// sensibly.
			sort.Slice(signedHashes, func(i, j int) bool {
				return string(signedHashes[i]) < string(signedHashes[j])
			})

			cb(provider, version, []getproviders.Hash{newHash}, signedHashes, priorHashes)
		}

		if cb := evts.FetchPackageSuccess; cb != nil {
			cb(provider, version, new.PackageDir, authResult)
		}
	}

	// Emit final event for fetching if any were successfully fetched
	if cb := evts.ProvidersFetched; cb != nil && len(authResults) > 0 {
		cb(authResults)
	}

	// Finally, if the lock structure contains locks for any providers that
	// are no longer needed by this configuration, we'll remove them. This
	// is important because we will not have installed those providers
	// above and so a lock file still containing them would make the working
	// directory invalid: not every provider in the lock file is available
	// for use.
	for providerAddr := range locks.AllProviders() {
		if _, ok := reqs[providerAddr]; !ok {
			locks.RemoveProvider(providerAddr)
		}
	}

	if len(errs) > 0 {
		return locks, InstallerError{
			ProviderErrors: errs,
		}
	}
	return locks, nil
}

// InstallMode customizes the details of how an install operation treats
// providers that have versions already cached in the target directory.
type InstallMode rune

const (
	// InstallNewProvidersOnly is an InstallMode that causes the installer
	// to accept any existing version of a requested provider that is already
	// cached as long as it's in the given version sets, without checking
	// whether new versions are available that are also in the given version
	// sets.
	InstallNewProvidersOnly InstallMode = 'N'

	// InstallNewProvidersForce is an InstallMode that follows the same
	// logic as InstallNewProvidersOnly except it does not verify existing
	// checksums but force installs new checksums for all given providers.
	InstallNewProvidersForce InstallMode = 'F'

	// InstallUpgrades is an InstallMode that causes the installer to check
	// all requested providers to see if new versions are available that
	// are also in the given version sets, even if a suitable version of
	// a given provider is already available.
	InstallUpgrades InstallMode = 'U'
)

func (m InstallMode) forceQueryAllProviders() bool {
	return m == InstallUpgrades
}

func (m InstallMode) forceInstallChecksums() bool {
	return m == InstallNewProvidersForce
}

// InstallerError is an error type that may be returned (but is not guaranteed)
// from Installer.EnsureProviderVersions to indicate potentially several
// separate failed installation outcomes for different providers included in
// the overall request.
type InstallerError struct {
	ProviderErrors map[addrs.Provider]error
}

func (err InstallerError) Error() string {
	addrs := make([]addrs.Provider, 0, len(err.ProviderErrors))
	for addr := range err.ProviderErrors {
		addrs = append(addrs, addr)
	}
	sort.Slice(addrs, func(i, j int) bool {
		return addrs[i].LessThan(addrs[j])
	})
	var b strings.Builder
	b.WriteString("some providers could not be installed:\n")
	for _, addr := range addrs {
		providerErr := err.ProviderErrors[addr]
		fmt.Fprintf(&b, "- %s: %s\n", addr, providerErr)
	}
	return strings.TrimSpace(b.String())
}
