package initwd

import (
	"context"
	"fmt"
	"io/ioutil"
	"log"
	"os"
	"path/filepath"
	"sort"
	"strings"

	"github.com/hashicorp/terraform/internal/copy"
	"github.com/hashicorp/terraform/internal/earlyconfig"
	"github.com/hashicorp/terraform/internal/getmodules"

	version "github.com/hashicorp/go-version"
	"github.com/hashicorp/terraform-config-inspect/tfconfig"
	"github.com/hashicorp/terraform/internal/modsdir"
	"github.com/hashicorp/terraform/internal/registry"
	"github.com/hashicorp/terraform/internal/tfdiags"
)

const initFromModuleRootCallName = "root"
const initFromModuleRootKeyPrefix = initFromModuleRootCallName + "."

// DirFromModule populates the given directory (which must exist and be
// empty) with the contents of the module at the given source address.
//
// It does this by installing the given module and all of its descendent
// modules in a temporary root directory and then copying the installed
// files into suitable locations. As a consequence, any diagnostics it
// generates will reveal the location of this temporary directory to the
// user.
//
// This rather roundabout installation approach is taken to ensure that
// installation proceeds in a manner identical to normal module installation.
//
// If the given source address specifies a sub-directory of the given
// package then only the sub-directory and its descendents will be copied
// into the given root directory, which will cause any relative module
// references using ../ from that module to be unresolvable. Error diagnostics
// are produced in that case, to prompt the user to rewrite the source strings
// to be absolute references to the original remote module.
func DirFromModule(ctx context.Context, rootDir, modulesDir, sourceAddr string, reg *registry.Client, hooks ModuleInstallHooks) tfdiags.Diagnostics {
	var diags tfdiags.Diagnostics

	// The way this function works is pretty ugly, but we accept it because
	// -from-module is a less important case than normal module installation
	// and so it's better to keep this ugly complexity out here rather than
	// adding even more complexity to the normal module installer.

	// The target directory must exist but be empty.
	{
		entries, err := ioutil.ReadDir(rootDir)
		if err != nil {
			if os.IsNotExist(err) {
				diags = diags.Append(tfdiags.Sourceless(
					tfdiags.Error,
					"Target directory does not exist",
					fmt.Sprintf("Cannot initialize non-existent directory %s.", rootDir),
				))
			} else {
				diags = diags.Append(tfdiags.Sourceless(
					tfdiags.Error,
					"Failed to read target directory",
					fmt.Sprintf("Error reading %s to ensure it is empty: %s.", rootDir, err),
				))
			}
			return diags
		}
		haveEntries := false
		for _, entry := range entries {
			if entry.Name() == "." || entry.Name() == ".." || entry.Name() == ".terraform" {
				continue
			}
			haveEntries = true
		}
		if haveEntries {
			diags = diags.Append(tfdiags.Sourceless(
				tfdiags.Error,
				"Can't populate non-empty directory",
				fmt.Sprintf("The target directory %s is not empty, so it cannot be initialized with the -from-module=... option.", rootDir),
			))
			return diags
		}
	}

	instDir := filepath.Join(rootDir, ".terraform/init-from-module")
	inst := NewModuleInstaller(instDir, reg)
	log.Printf("[DEBUG] installing modules in %s to initialize working directory from %q", instDir, sourceAddr)
	os.RemoveAll(instDir) // if this fails then we'll fail on MkdirAll below too
	err := os.MkdirAll(instDir, os.ModePerm)
	if err != nil {
		diags = diags.Append(tfdiags.Sourceless(
			tfdiags.Error,
			"Failed to create temporary directory",
			fmt.Sprintf("Failed to create temporary directory %s: %s.", instDir, err),
		))
		return diags
	}

	instManifest := make(modsdir.Manifest)
	retManifest := make(modsdir.Manifest)

	fakeFilename := fmt.Sprintf("-from-module=%q", sourceAddr)
	fakePos := tfconfig.SourcePos{
		Filename: fakeFilename,
		Line:     1,
	}

	// -from-module allows relative paths but it's different than a normal
	// module address where it'd be resolved relative to the module call
	// (which is synthetic, here.) To address this, we'll just patch up any
	// relative paths to be absolute paths before we run, ensuring we'll
	// get the right result. This also, as an important side-effect, ensures
	// that the result will be "downloaded" with go-getter (copied from the
	// source location), rather than just recorded as a relative path.
	{
		maybePath := filepath.ToSlash(sourceAddr)
		if maybePath == "." || strings.HasPrefix(maybePath, "./") || strings.HasPrefix(maybePath, "../") {
			if wd, err := os.Getwd(); err == nil {
				sourceAddr = filepath.Join(wd, sourceAddr)
				log.Printf("[TRACE] -from-module relative path rewritten to absolute path %s", sourceAddr)
			}
		}
	}

	// Now we need to create an artificial root module that will seed our
	// installation process.
	fakeRootModule := &tfconfig.Module{
		ModuleCalls: map[string]*tfconfig.ModuleCall{
			initFromModuleRootCallName: {
				Name:   initFromModuleRootCallName,
				Source: sourceAddr,
				Pos:    fakePos,
			},
		},
	}

	// wrapHooks filters hook notifications to only include Download calls
	// and to trim off the initFromModuleRootCallName prefix. We'll produce
	// our own Install notifications directly below.
	wrapHooks := installHooksInitDir{
		Wrapped: hooks,
	}
	fetcher := getmodules.NewPackageFetcher()
	_, instDiags := inst.installDescendentModules(ctx, fakeRootModule, rootDir, instManifest, true, wrapHooks, fetcher)
	diags = append(diags, instDiags...)
	if instDiags.HasErrors() {
		return diags
	}

	// If all of that succeeded then we'll now migrate what was installed
	// into the final directory structure.
	err = os.MkdirAll(modulesDir, os.ModePerm)
	if err != nil {
		diags = diags.Append(tfdiags.Sourceless(
			tfdiags.Error,
			"Failed to create local modules directory",
			fmt.Sprintf("Failed to create modules directory %s: %s.", modulesDir, err),
		))
		return diags
	}

	recordKeys := make([]string, 0, len(instManifest))
	for k := range instManifest {
		recordKeys = append(recordKeys, k)
	}
	sort.Strings(recordKeys)

	for _, recordKey := range recordKeys {
		record := instManifest[recordKey]

		if record.Key == initFromModuleRootCallName {
			// We've found the module the user requested, which we must
			// now copy into rootDir so it can be used directly.
			log.Printf("[TRACE] copying new root module from %s to %s", record.Dir, rootDir)
			err := copy.CopyDir(rootDir, record.Dir)
			if err != nil {
				diags = diags.Append(tfdiags.Sourceless(
					tfdiags.Error,
					"Failed to copy root module",
					fmt.Sprintf("Error copying root module %q from %s to %s: %s.", sourceAddr, record.Dir, rootDir, err),
				))
				continue
			}

			// We'll try to load the newly-copied module here just so we can
			// sniff for any module calls that ../ out of the root directory
			// and must thus be rewritten to be absolute addresses again.
			// For now we can't do this rewriting automatically, but we'll
			// generate an error to help the user do it manually.
			mod, _ := earlyconfig.LoadModule(rootDir) // ignore diagnostics since we're just doing value-add here anyway
			if mod != nil {
				for _, mc := range mod.ModuleCalls {
					if pathTraversesUp(mc.Source) {
						packageAddr, givenSubdir := getmodules.SplitPackageSubdir(sourceAddr)
						newSubdir := filepath.Join(givenSubdir, mc.Source)
						if pathTraversesUp(newSubdir) {
							// This should never happen in any reasonable
							// configuration since this suggests a path that
							// traverses up out of the package root. We'll just
							// ignore this, since we'll fail soon enough anyway
							// trying to resolve this path when this module is
							// loaded.
							continue
						}

						var newAddr = packageAddr
						if newSubdir != "" {
							newAddr = fmt.Sprintf("%s//%s", newAddr, filepath.ToSlash(newSubdir))
						}
						diags = diags.Append(tfdiags.Sourceless(
							tfdiags.Error,
							"Root module references parent directory",
							fmt.Sprintf("The requested module %q refers to a module via its parent directory. To use this as a new root module this source string must be rewritten as a remote source address, such as %q.", sourceAddr, newAddr),
						))
						continue
					}
				}
			}

			retManifest[""] = modsdir.Record{
				Key: "",
				Dir: rootDir,
			}
			continue
		}

		if !strings.HasPrefix(record.Key, initFromModuleRootKeyPrefix) {
			// Ignore the *real* root module, whose key is empty, since
			// we're only interested in the module named "root" and its
			// descendents.
			continue
		}

		newKey := record.Key[len(initFromModuleRootKeyPrefix):]
		instPath := filepath.Join(modulesDir, newKey)
		tempPath := filepath.Join(instDir, record.Key)

		// tempPath won't be present for a module that was installed from
		// a relative path, so in that case we just record the installation
		// directory and assume it was already copied into place as part
		// of its parent.
		if _, err := os.Stat(tempPath); err != nil {
			if !os.IsNotExist(err) {
				diags = diags.Append(tfdiags.Sourceless(
					tfdiags.Error,
					"Failed to stat temporary module install directory",
					fmt.Sprintf("Error from stat %s for module %s: %s.", instPath, newKey, err),
				))
				continue
			}

			var parentKey string
			if lastDot := strings.LastIndexByte(newKey, '.'); lastDot != -1 {
				parentKey = newKey[:lastDot]
			}

			var parentOld modsdir.Record
			// "" is the root module; all other modules get `root.` added as a prefix
			if parentKey == "" {
				parentOld = instManifest[parentKey]
			} else {
				parentOld = instManifest[initFromModuleRootKeyPrefix+parentKey]
			}
			parentNew := retManifest[parentKey]

			// We need to figure out which portion of our directory is the
			// parent package path and which portion is the subdirectory
			// under that.
			var baseDirRel string
			baseDirRel, err = filepath.Rel(parentOld.Dir, record.Dir)
			if err != nil {
				// This error may occur when installing a local module with a
				// relative path, for e.g. if the source is in a directory above
				// the destination ("../")
				if parentOld.Dir == "." {
					absDir, err := filepath.Abs(parentOld.Dir)
					if err != nil {
						diags = diags.Append(tfdiags.Sourceless(
							tfdiags.Error,
							"Failed to determine module install directory",
							fmt.Sprintf("Error determine relative source directory for module %s: %s.", newKey, err),
						))
						continue
					}
					baseDirRel, err = filepath.Rel(absDir, record.Dir)
					if err != nil {
						diags = diags.Append(tfdiags.Sourceless(
							tfdiags.Error,
							"Failed to determine relative module source location",
							fmt.Sprintf("Error determining relative source for module %s: %s.", newKey, err),
						))
						continue
					}
				} else {
					diags = diags.Append(tfdiags.Sourceless(
						tfdiags.Error,
						"Failed to determine relative module source location",
						fmt.Sprintf("Error determining relative source for module %s: %s.", newKey, err),
					))
				}
			}

			newDir := filepath.Join(parentNew.Dir, baseDirRel)
			log.Printf("[TRACE] relative reference for %s rewritten from %s to %s", newKey, record.Dir, newDir)
			newRecord := record // shallow copy
			newRecord.Dir = newDir
			newRecord.Key = newKey
			retManifest[newKey] = newRecord
			hooks.Install(newRecord.Key, newRecord.Version, newRecord.Dir)
			continue
		}

		err = os.MkdirAll(instPath, os.ModePerm)
		if err != nil {
			diags = diags.Append(tfdiags.Sourceless(
				tfdiags.Error,
				"Failed to create module install directory",
				fmt.Sprintf("Error creating directory %s for module %s: %s.", instPath, newKey, err),
			))
			continue
		}

		// We copy rather than "rename" here because renaming between directories
		// can be tricky in edge-cases like network filesystems, etc.
		log.Printf("[TRACE] copying new module %s from %s to %s", newKey, record.Dir, instPath)
		err := copy.CopyDir(instPath, tempPath)
		if err != nil {
			diags = diags.Append(tfdiags.Sourceless(
				tfdiags.Error,
				"Failed to copy descendent module",
				fmt.Sprintf("Error copying module %q from %s to %s: %s.", newKey, tempPath, rootDir, err),
			))
			continue
		}

		subDir, err := filepath.Rel(tempPath, record.Dir)
		if err != nil {
			// Should never happen, because we constructed both directories
			// from the same base and so they must have a common prefix.
			panic(err)
		}

		newRecord := record // shallow copy
		newRecord.Dir = filepath.Join(instPath, subDir)
		newRecord.Key = newKey
		retManifest[newKey] = newRecord
		hooks.Install(newRecord.Key, newRecord.Version, newRecord.Dir)
	}

	retManifest.WriteSnapshotToDir(modulesDir)
	if err != nil {
		diags = diags.Append(tfdiags.Sourceless(
			tfdiags.Error,
			"Failed to write module manifest",
			fmt.Sprintf("Error writing module manifest: %s.", err),
		))
	}

	if !diags.HasErrors() {
		// Try to clean up our temporary directory, but don't worry if we don't
		// succeed since it shouldn't hurt anything.
		os.RemoveAll(instDir)
	}

	return diags
}

func pathTraversesUp(path string) bool {
	return strings.HasPrefix(filepath.ToSlash(path), "../")
}

// installHooksInitDir is an adapter wrapper for an InstallHooks that
// does some fakery to make downloads look like they are happening in their
// final locations, rather than in the temporary loader we use.
//
// It also suppresses "Install" calls entirely, since InitDirFromModule
// does its own installation steps after the initial installation pass
// has completed.
type installHooksInitDir struct {
	Wrapped ModuleInstallHooks
	ModuleInstallHooksImpl
}

func (h installHooksInitDir) Download(moduleAddr, packageAddr string, version *version.Version) {
	if !strings.HasPrefix(moduleAddr, initFromModuleRootKeyPrefix) {
		// We won't announce the root module, since hook implementations
		// don't expect to see that and the caller will usually have produced
		// its own user-facing notification about what it's doing anyway.
		return
	}

	trimAddr := moduleAddr[len(initFromModuleRootKeyPrefix):]
	h.Wrapped.Download(trimAddr, packageAddr, version)
}
