// Copyright 2018 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package packagestest

import (
	"bytes"
	"context"
	"fmt"
	"os"
	"path"
	"path/filepath"
	"regexp"
	"strings"

	"golang.org/x/tools/internal/gocommand"
	"golang.org/x/tools/internal/proxydir"
)

// Modules is the exporter that produces module layouts.
// Each "repository" is put in its own module, and the module file generated
// will have replace directives for all other modules.
// Given the two files
//
//	golang.org/repoa#a/a.go
//	golang.org/repob#b/b.go
//
// You would get the directory layout
//
//	/sometemporarydirectory
//	├── repoa
//	│   ├── a
//	│   │   └── a.go
//	│   └── go.mod
//	└── repob
//	    ├── b
//	    │   └── b.go
//	    └── go.mod
//
// and the working directory would be
//
//	/sometemporarydirectory/repoa
var Modules = modules{}

type modules struct{}

type moduleAtVersion struct {
	module  string
	version string
}

func (modules) Name() string {
	return "Modules"
}

func (modules) Filename(exported *Exported, module, fragment string) string {
	if module == exported.primary {
		return filepath.Join(primaryDir(exported), fragment)
	}
	return filepath.Join(moduleDir(exported, module), fragment)
}

func (modules) Finalize(exported *Exported) error {
	// Write out the primary module. This module can use symlinks and
	// other weird stuff, and will be the working dir for the go command.
	// It depends on all the other modules.
	primaryDir := primaryDir(exported)
	if err := os.MkdirAll(primaryDir, 0755); err != nil {
		return err
	}
	exported.Config.Dir = primaryDir
	if exported.written[exported.primary] == nil {
		exported.written[exported.primary] = make(map[string]string)
	}

	// Create a map of modulepath -> {module, version} for modulepaths
	// that are of the form `repoa/mod1@v1.1.0`.
	versions := make(map[string]moduleAtVersion)
	for module := range exported.written {
		if splt := strings.Split(module, "@"); len(splt) > 1 {
			versions[module] = moduleAtVersion{
				module:  splt[0],
				version: splt[1],
			}
		}
	}

	// If the primary module already has a go.mod, write the contents to a temp
	// go.mod for now and then we will reset it when we are getting all the markers.
	if gomod := exported.written[exported.primary]["go.mod"]; gomod != "" {
		contents, err := os.ReadFile(gomod)
		if err != nil {
			return err
		}
		if err := os.WriteFile(gomod+".temp", contents, 0644); err != nil {
			return err
		}
	}

	exported.written[exported.primary]["go.mod"] = filepath.Join(primaryDir, "go.mod")
	var primaryGomod bytes.Buffer
	fmt.Fprintf(&primaryGomod, "module %s\nrequire (\n", exported.primary)
	for other := range exported.written {
		if other == exported.primary {
			continue
		}
		version := moduleVersion(other)
		// If other is of the form `repo1/mod1@v1.1.0`,
		// then we need to extract the module and the version.
		if v, ok := versions[other]; ok {
			other = v.module
			version = v.version
		}
		fmt.Fprintf(&primaryGomod, "\t%v %v\n", other, version)
	}
	fmt.Fprintf(&primaryGomod, ")\n")
	if err := os.WriteFile(filepath.Join(primaryDir, "go.mod"), primaryGomod.Bytes(), 0644); err != nil {
		return err
	}

	// Create the mod cache so we can rename it later, even if we don't need it.
	if err := os.MkdirAll(modCache(exported), 0755); err != nil {
		return err
	}

	// Write out the go.mod files for the other modules.
	for module, files := range exported.written {
		if module == exported.primary {
			continue
		}
		dir := moduleDir(exported, module)
		modfile := filepath.Join(dir, "go.mod")
		// If other is of the form `repo1/mod1@v1.1.0`,
		// then we need to extract the module name without the version.
		if v, ok := versions[module]; ok {
			module = v.module
		}
		if err := os.WriteFile(modfile, []byte("module "+module+"\n"), 0644); err != nil {
			return err
		}
		files["go.mod"] = modfile
	}

	// Zip up all the secondary modules into the proxy dir.
	modProxyDir := filepath.Join(exported.temp, "modproxy")
	for module, files := range exported.written {
		if module == exported.primary {
			continue
		}
		version := moduleVersion(module)
		// If other is of the form `repo1/mod1@v1.1.0`,
		// then we need to extract the module and the version.
		if v, ok := versions[module]; ok {
			module = v.module
			version = v.version
		}
		if err := writeModuleFiles(modProxyDir, module, version, files); err != nil {
			return fmt.Errorf("creating module proxy dir for %v: %v", module, err)
		}
	}

	// Discard the original mod cache dir, which contained the files written
	// for us by Export.
	if err := os.Rename(modCache(exported), modCache(exported)+".orig"); err != nil {
		return err
	}
	exported.Config.Env = append(exported.Config.Env,
		"GO111MODULE=on",
		"GOPATH="+filepath.Join(exported.temp, "modcache"),
		"GOMODCACHE=",
		"GOPROXY="+proxydir.ToURL(modProxyDir),
		"GOSUMDB=off",
	)

	// Run go mod download to recreate the mod cache dir with all the extra
	// stuff in cache. All the files created by Export should be recreated.
	inv := gocommand.Invocation{
		Verb:       "mod",
		Args:       []string{"download", "all"},
		Env:        exported.Config.Env,
		BuildFlags: exported.Config.BuildFlags,
		WorkingDir: exported.Config.Dir,
	}
	_, err := new(gocommand.Runner).Run(context.Background(), inv)
	return err
}

func writeModuleFiles(rootDir, module, ver string, filePaths map[string]string) error {
	fileData := make(map[string][]byte)
	for name, path := range filePaths {
		contents, err := os.ReadFile(path)
		if err != nil {
			return err
		}
		fileData[name] = contents
	}
	return proxydir.WriteModuleVersion(rootDir, module, ver, fileData)
}

func modCache(exported *Exported) string {
	return filepath.Join(exported.temp, "modcache/pkg/mod")
}

func primaryDir(exported *Exported) string {
	return filepath.Join(exported.temp, path.Base(exported.primary))
}

func moduleDir(exported *Exported, module string) string {
	if strings.Contains(module, "@") {
		return filepath.Join(modCache(exported), module)
	}
	return filepath.Join(modCache(exported), path.Dir(module), path.Base(module)+"@"+moduleVersion(module))
}

var versionSuffixRE = regexp.MustCompile(`v\d+`)

func moduleVersion(module string) string {
	if versionSuffixRE.MatchString(path.Base(module)) {
		return path.Base(module) + ".0.0"
	}
	return "v1.0.0"
}
