// Copyright 2019 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 fetch provides a way to fetch modules from a proxy.
package fetch

import (
	"context"
	"errors"
	"fmt"
	"io/fs"
	"path"
	"runtime/debug"
	"strings"
	"sync"

	"golang.org/x/mod/module"
	"golang.org/x/pkgsite/internal"
	"golang.org/x/pkgsite/internal/derrors"
	"golang.org/x/pkgsite/internal/godoc"
	"golang.org/x/pkgsite/internal/licenses"
	"golang.org/x/pkgsite/internal/log"
	"golang.org/x/pkgsite/internal/source"
	"golang.org/x/pkgsite/internal/stdlib"
	"golang.org/x/pkgsite/internal/trace"
	"golang.org/x/sync/errgroup"
)

// A goPackage is a group of one or more Go source files with the same
// package header. Packages are part of a module.
type goPackage struct {
	path              string
	name              string
	imports           []string
	isRedistributable bool
	licenseMeta       []*licenses.Metadata // metadata of applicable licenses
	// v1path is the package path of a package with major version 1 in a given
	// series.
	v1path string
	docs   []*internal.Documentation // doc for different build contexts
	err    error                     // non-fatal error when loading the package (e.g. documentation is too large)
}

// rel returns the relative path from the modulePath to the pkgPath
// returning "." if they're the same.
func rel(pkgPath, modulePath string) string {
	suff := internal.Suffix(pkgPath, modulePath)
	if suff == "" {
		return "."
	}
	return suff
}

// extractPackage returns a package from a filesystem arranged like a module zip.
// It matches against the given licenses to determine the subset of licenses
// that applies to each package.
// It returns a packageVersionState representing the status of doing the work
// of computing the package after the UnitMeta was computed. The packageVersionState
// of a package that failed to have a UnitMeta produced was produced by extractPackageMetas.
func extractPackage(ctx context.Context, modulePath, pkgPath string, contentDir fs.FS, d *licenses.Detector, sourceInfo *source.Info, modInfo *godoc.ModuleInfo) (*goPackage, *internal.PackageVersionState, error) {
	innerPath := rel(pkgPath, modulePath)
	f, err := contentDir.Open(innerPath)
	if err != nil {
		return nil, nil, err
	}
	dir, ok := f.(fs.ReadDirFile)
	if !ok {
		return nil, nil, fmt.Errorf("file is not a directory")
	}
	entries, err := dir.ReadDir(0)
	if err != nil {
		panic(err)
	}
	var goFiles []string
	for _, e := range entries {
		if e.IsDir() {
			continue
		}
		if !strings.HasSuffix(e.Name(), ".go") {
			// We care about .go files only.
			continue
		}
		goFiles = append(goFiles, path.Join(innerPath, e.Name()))
	}
	if len(goFiles) == 0 {
		// We shouldn't be here, because we only call extratPackage for package units.
		return nil, nil, fmt.Errorf("extractPackage called but no go files: modulePath=%s, pkgPath=%q", modulePath, pkgPath)
	}

	var (
		status error
		errMsg string
	)
	pkg, err := loadPackage(ctx, contentDir, goFiles, innerPath, sourceInfo, modInfo)
	if bpe := (*BadPackageError)(nil); errors.As(err, &bpe) {
		log.Infof(ctx, "Error loading %s: %v", innerPath, err)
		status = derrors.PackageInvalidContents
		errMsg = err.Error()
	} else if err != nil {
		return nil, nil, fmt.Errorf("unexpected error loading package: %v", err)
	}

	if pkg == nil {
		// No package.
		if len(goFiles) > 0 {
			// There were go files, but no build contexts matched them.
			status = derrors.PackageBuildContextNotSupported
		}
	} else {
		if errors.Is(pkg.err, godoc.ErrTooLarge) {
			status = derrors.PackageDocumentationHTMLTooLarge
			errMsg = pkg.err.Error()
		} else if pkg.err != nil {
			// ErrTooLarge is the only valid value of pkg.err.
			return nil, nil, fmt.Errorf("bad package error for %s: %v", pkg.path, pkg.err)
		}
		if d != nil { //  should only be nil for tests
			isRedist, lics := d.PackageInfo(innerPath)
			pkg.isRedistributable = isRedist
			for _, l := range lics {
				pkg.licenseMeta = append(pkg.licenseMeta, l.Metadata)
			}
		}
	}

	pvs := &internal.PackageVersionState{
		ModulePath:  modulePath,
		PackagePath: pkgPath,
		Version:     modInfo.ResolvedVersion,
		Status:      derrors.ToStatus(status),
		Error:       errMsg,
	}

	return pkg, pvs, nil
}

type packageMeta struct {
	path     string
	name     string
	synopsis string
}

// extractPackageMetas returns a slice of packageMetas containing only the information
// needed to produce a UnitMeta from filesystem arranged like a module zip. extractPackage
// does the work to complete the package with all the information needed for a Unit.
// It matches against the given licenses to determine the subset of licenses
// that applies to each package.
// The second return value says whether any packages are "incomplete," meaning
// that they contained .go files but couldn't be processed due to current
// limitations of this site. The limitations are:
// * a maximum file size (MaxFileSize)
// * the particular set of build contexts we consider (goEnvs)
// * whether the import path is valid.
func extractPackageMetas(ctx context.Context, modulePath, resolvedVersion string, contentDir fs.FS) (_ []*packageMeta, _ *godoc.ModuleInfo, _ []*internal.PackageVersionState, err error) {
	defer derrors.Wrap(&err, "extractPackages(ctx, %q, %q, r, d)", modulePath, resolvedVersion)
	ctx, span := trace.StartSpan(ctx, "fetch.extractPackages")
	defer span.End()
	defer func() {
		if e := recover(); e != nil {
			// The package processing code performs some sanity checks along the way.
			// None of the panics should occur, but if they do, we want to log them and
			// be able to find them. So, convert internal panics to internal errors here.
			err = fmt.Errorf("internal panic: %v\n\n%s", e, debug.Stack())
		}
	}()

	// The high-level approach is to split the processing of the zip file
	// into two phases:
	//
	// 	1. loop over all files, looking at file metadata only
	// 	2. process all files by reading their contents
	//
	// During phase 1, we populate the dirs map for each directory
	// that contains at least one .go file.

	var (
		// dirs is the set of directories with at least one .go file,
		// to be populated during phase 1 and used during phase 2.
		//
		// The map key is the directory path, with the modulePrefix trimmed.
		// The map value is a slice of all .go file paths, and no other files.
		dirs = make(map[string][]string)

		// modInfo contains all the module information a package in the module
		// needs to render its documentation, to be populated during phase 1
		// and used during phase 2.
		modInfo = &godoc.ModuleInfo{
			ModulePath:      modulePath,
			ResolvedVersion: resolvedVersion,
			ModulePackages:  make(map[string]bool),
		}

		// incompleteDirs tracks directories for which we have incomplete
		// information, due to a problem processing one of the go files contained
		// therein. We use this so that a single unprocessable package does not
		// prevent processing of other packages in the module.
		incompleteDirs       = make(map[string]bool)
		packageVersionStates = []*internal.PackageVersionState{}
	)

	// Phase 1.
	// Loop over zip files preemptively and check for problems
	// that can be detected by looking at metadata alone.
	// We'll be looking at file contents starting with phase 2 only,
	// only after we're sure this phase passed without errors.
	err = fs.WalkDir(contentDir, ".", func(pathname string, d fs.DirEntry, err error) error {
		if err != nil {
			return err
		}
		if d.IsDir() {
			// Skip directories.
			return nil
		}
		innerPath := path.Dir(pathname)
		if incompleteDirs[innerPath] {
			// We already know this directory cannot be processed, so skip.
			return nil
		}
		importPath := path.Join(modulePath, innerPath)
		if modulePath == stdlib.ModulePath {
			importPath = innerPath
		}
		if ignoredByGoTool(importPath) || isVendored(importPath) {
			// File is in a directory we're not looking to process at this time, so skip it.
			return nil
		}
		if !strings.HasSuffix(pathname, ".go") {
			// We care about .go files only.
			return nil
		}
		// It's possible to have a Go package in a directory that does not result in a valid import path.
		// That package cannot be imported, but that may be fine if it's a main package, intended to built
		// and run from that directory.
		// Example:  https://github.com/postmannen/go-learning/blob/master/concurrency/01-sending-numbers-and-receving-numbers-from-a-channel/main.go
		// We're not set up to handle invalid import paths, so skip these packages.
		if err := module.CheckImportPath(importPath); err != nil {
			incompleteDirs[innerPath] = true
			packageVersionStates = append(packageVersionStates, &internal.PackageVersionState{
				ModulePath:  modulePath,
				PackagePath: importPath,
				Version:     resolvedVersion,
				Status:      derrors.ToStatus(derrors.PackageBadImportPath),
				Error:       err.Error(),
			})
			return nil
		}
		info, err := d.Info()
		if err != nil {
			return err
		}
		if info.Size() > MaxFileSize {
			incompleteDirs[innerPath] = true
			status := derrors.ToStatus(derrors.PackageMaxFileSizeLimitExceeded)
			err := fmt.Sprintf("Unable to process %s: file size %d exceeds max limit %d",
				pathname, info.Size(), MaxFileSize)
			packageVersionStates = append(packageVersionStates, &internal.PackageVersionState{
				ModulePath:  modulePath,
				PackagePath: importPath,
				Version:     resolvedVersion,
				Status:      status,
				Error:       err,
			})
			return nil
		}
		dirs[innerPath] = append(dirs[innerPath], pathname)
		if len(dirs) > maxPackagesPerModule {
			return fmt.Errorf("%d packages found in %q; exceeds limit %d for maxPackagePerModule: %w",
				len(dirs), modulePath, maxPackagesPerModule, derrors.ModuleTooLarge)
		}
		return nil
	})
	if errors.Is(err, fs.ErrNotExist) {
		return nil, nil, nil, fmt.Errorf("no files: %w", ErrModuleContainsNoPackages)
	}
	if err != nil {
		return nil, nil, nil, err
	}

	for pkgName := range dirs {
		modInfo.ModulePackages[path.Join(modulePath, pkgName)] = true
	}

	// Phase 2.
	// If we got this far, the file metadata was okay.
	// Start reading the file contents now to extract information
	// about Go packages.
	var pkgs []*packageMeta
	var mu sync.Mutex // guards pkgs, incompleteDirs, packageVersionStates
	var errgroup errgroup.Group
	for innerPath, goFiles := range dirs {
		errgroup.Go(func() error {
			var addedPackage bool
			mu.Lock()
			incomplete := incompleteDirs[innerPath]
			mu.Unlock()
			if incomplete {
				// Something went wrong when processing this directory, so we skip.
				log.Infof(ctx, "Skipping %q because it is incomplete", innerPath)
				return nil
			}

			var (
				status error
				errMsg string
			)
			pkg, err := loadPackageMeta(ctx, contentDir, goFiles, innerPath, modInfo)
			if bpe := (*BadPackageError)(nil); errors.As(err, &bpe) {
				log.Infof(ctx, "Error loading %s: %v", innerPath, err)
				mu.Lock()
				incompleteDirs[innerPath] = true
				mu.Unlock()
				status = derrors.PackageInvalidContents
				errMsg = err.Error()
			} else if err != nil {
				return fmt.Errorf("unexpected error loading package: %v", err)
			}
			var pkgPath string
			if pkg == nil {
				// No package.
				if len(goFiles) > 0 {
					// There were go files, but no build contexts matched them.
					mu.Lock()
					incompleteDirs[innerPath] = true
					mu.Unlock()
					status = derrors.PackageBuildContextNotSupported
				}
				pkgPath = path.Join(modulePath, innerPath)
				if modulePath == stdlib.ModulePath {
					pkgPath = innerPath
				}
			} else {
				mu.Lock()
				pkgs = append(pkgs, pkg)
				mu.Unlock()
				addedPackage = true
				pkgPath = pkg.path
			}
			if !addedPackage {
				mu.Lock()
				packageVersionStates = append(packageVersionStates, &internal.PackageVersionState{
					ModulePath:  modulePath,
					PackagePath: pkgPath,
					Version:     resolvedVersion,
					Status:      derrors.ToStatus(status),
					Error:       errMsg,
				})
				mu.Unlock()
			}

			return nil
		})
	}

	if err := errgroup.Wait(); err != nil {
		return nil, nil, nil, err
	}

	if len(pkgs) == 0 {
		return nil, nil, packageVersionStates, ErrModuleContainsNoPackages
	}
	return pkgs, modInfo, packageVersionStates, nil
}

// ignoredByGoTool reports whether the given import path corresponds
// to a directory that would be ignored by the go tool.
//
// The logic of the go tool for ignoring directories is documented at
// https://golang.org/cmd/go/#hdr-Package_lists_and_patterns:
//
//	Directory and file names that begin with "." or "_" are ignored
//	by the go tool, as are directories named "testdata".
//
// However, even though `go list` and other commands that take package
// wildcards will ignore these, they can still be imported and used in
// working Go programs. We continue to ignore the "." and "testdata"
// cases, but we've seen valid Go packages with "_", so we accept those.
func ignoredByGoTool(importPath string) bool {
	for el := range strings.SplitSeq(importPath, "/") {
		if strings.HasPrefix(el, ".") || el == "testdata" {
			return true
		}
	}
	return false
}

// isVendored reports whether the given import path corresponds
// to a Go package that is inside a vendor directory.
//
// The logic for what is considered a vendor directory is documented at
// https://golang.org/cmd/go/#hdr-Vendor_Directories.
func isVendored(importPath string) bool {
	return strings.HasPrefix(importPath, "vendor/") ||
		strings.Contains(importPath, "/vendor/")
}
