// 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 mod provides core features related to go.mod file
// handling for use by Go editors and tools.
package mod

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

	"golang.org/x/mod/modfile"
	"golang.org/x/mod/semver"
	"golang.org/x/tools/gopls/internal/govulncheck"
	"golang.org/x/tools/gopls/internal/lsp/command"
	"golang.org/x/tools/gopls/internal/lsp/protocol"
	"golang.org/x/tools/gopls/internal/lsp/source"
	"golang.org/x/tools/gopls/internal/span"
	"golang.org/x/tools/internal/event"
	"golang.org/x/vuln/osv"
)

// Diagnostics returns diagnostics for the modules in the workspace.
//
// It waits for completion of type-checking of all active packages.
func Diagnostics(ctx context.Context, snapshot source.Snapshot) (map[span.URI][]*source.Diagnostic, error) {
	ctx, done := event.Start(ctx, "mod.Diagnostics", source.SnapshotLabels(snapshot)...)
	defer done()

	return collectDiagnostics(ctx, snapshot, ModDiagnostics)
}

// UpgradeDiagnostics returns upgrade diagnostics for the modules in the
// workspace with known upgrades.
func UpgradeDiagnostics(ctx context.Context, snapshot source.Snapshot) (map[span.URI][]*source.Diagnostic, error) {
	ctx, done := event.Start(ctx, "mod.UpgradeDiagnostics", source.SnapshotLabels(snapshot)...)
	defer done()

	return collectDiagnostics(ctx, snapshot, ModUpgradeDiagnostics)
}

// VulnerabilityDiagnostics returns vulnerability diagnostics for the active modules in the
// workspace with known vulnerabilites.
func VulnerabilityDiagnostics(ctx context.Context, snapshot source.Snapshot) (map[span.URI][]*source.Diagnostic, error) {
	ctx, done := event.Start(ctx, "mod.VulnerabilityDiagnostics", source.SnapshotLabels(snapshot)...)
	defer done()

	return collectDiagnostics(ctx, snapshot, ModVulnerabilityDiagnostics)
}

func collectDiagnostics(ctx context.Context, snapshot source.Snapshot, diagFn func(context.Context, source.Snapshot, source.FileHandle) ([]*source.Diagnostic, error)) (map[span.URI][]*source.Diagnostic, error) {
	reports := make(map[span.URI][]*source.Diagnostic)
	for _, uri := range snapshot.ModFiles() {
		fh, err := snapshot.GetFile(ctx, uri)
		if err != nil {
			return nil, err
		}
		reports[fh.URI()] = []*source.Diagnostic{}
		diagnostics, err := diagFn(ctx, snapshot, fh)
		if err != nil {
			return nil, err
		}
		for _, d := range diagnostics {
			fh, err := snapshot.GetFile(ctx, d.URI)
			if err != nil {
				return nil, err
			}
			reports[fh.URI()] = append(reports[fh.URI()], d)
		}
	}
	return reports, nil
}

// ModDiagnostics waits for completion of type-checking of all active
// packages, then returns diagnostics from diagnosing the packages in
// the workspace and from tidying the go.mod file.
func ModDiagnostics(ctx context.Context, snapshot source.Snapshot, fh source.FileHandle) (diagnostics []*source.Diagnostic, err error) {
	pm, err := snapshot.ParseMod(ctx, fh)
	if err != nil {
		if pm == nil || len(pm.ParseErrors) == 0 {
			return nil, err
		}
		return pm.ParseErrors, nil
	}

	// Packages in the workspace can contribute diagnostics to go.mod files.
	// TODO(rfindley): Try to avoid type checking all packages in the workspace here,
	// for every go.mod file. If gc_details is enabled, it looks like this could lead to extra
	// go command invocations (as gc details is not memoized).
	active, err := snapshot.ActiveMetadata(ctx)
	if err != nil && !source.IsNonFatalGoModError(err) {
		event.Error(ctx, fmt.Sprintf("workspace packages: diagnosing %s", pm.URI), err)
	}
	if err == nil {
		// Type-check packages in parallel and gather list/parse/type errors.
		// (This may be the first operation after the initial metadata load
		// to demand type-checking of all active packages.)
		ids := make([]source.PackageID, len(active))
		for i, meta := range active {
			ids[i] = meta.ID
		}
		pkgs, err := snapshot.TypeCheck(ctx, source.TypecheckFull, ids...)
		if err != nil {
			return nil, err
		}
		for _, pkg := range pkgs {
			diagnostics = append(diagnostics, pkg.DiagnosticsForFile(fh.URI())...)
		}
	}

	tidied, err := snapshot.ModTidy(ctx, pm)
	if err != nil && !source.IsNonFatalGoModError(err) {
		event.Error(ctx, fmt.Sprintf("tidy: diagnosing %s", pm.URI), err)
	}
	if err == nil {
		for _, d := range tidied.Diagnostics {
			if d.URI != fh.URI() {
				continue
			}
			diagnostics = append(diagnostics, d)
		}
	}
	return diagnostics, nil
}

// ModUpgradeDiagnostics adds upgrade quick fixes for individual modules if the upgrades
// are recorded in the view.
func ModUpgradeDiagnostics(ctx context.Context, snapshot source.Snapshot, fh source.FileHandle) (upgradeDiagnostics []*source.Diagnostic, err error) {
	pm, err := snapshot.ParseMod(ctx, fh)
	if err != nil {
		// Don't return an error if there are parse error diagnostics to be shown, but also do not
		// continue since we won't be able to show the upgrade diagnostics.
		if pm != nil && len(pm.ParseErrors) != 0 {
			return nil, nil
		}
		return nil, err
	}

	upgrades := snapshot.View().ModuleUpgrades(fh.URI())
	for _, req := range pm.File.Require {
		ver, ok := upgrades[req.Mod.Path]
		if !ok || req.Mod.Version == ver {
			continue
		}
		rng, err := pm.Mapper.OffsetRange(req.Syntax.Start.Byte, req.Syntax.End.Byte)
		if err != nil {
			return nil, err
		}
		// Upgrade to the exact version we offer the user, not the most recent.
		title := fmt.Sprintf("%s%v", upgradeCodeActionPrefix, ver)
		cmd, err := command.NewUpgradeDependencyCommand(title, command.DependencyArgs{
			URI:        protocol.URIFromSpanURI(fh.URI()),
			AddRequire: false,
			GoCmdArgs:  []string{req.Mod.Path + "@" + ver},
		})
		if err != nil {
			return nil, err
		}
		upgradeDiagnostics = append(upgradeDiagnostics, &source.Diagnostic{
			URI:            fh.URI(),
			Range:          rng,
			Severity:       protocol.SeverityInformation,
			Source:         source.UpgradeNotification,
			Message:        fmt.Sprintf("%v can be upgraded", req.Mod.Path),
			SuggestedFixes: []source.SuggestedFix{source.SuggestedFixFromCommand(cmd, protocol.QuickFix)},
		})
	}

	return upgradeDiagnostics, nil
}

const upgradeCodeActionPrefix = "Upgrade to "

// ModVulnerabilityDiagnostics adds diagnostics for vulnerabilities in individual modules
// if the vulnerability is recorded in the view.
func ModVulnerabilityDiagnostics(ctx context.Context, snapshot source.Snapshot, fh source.FileHandle) (vulnDiagnostics []*source.Diagnostic, err error) {
	pm, err := snapshot.ParseMod(ctx, fh)
	if err != nil {
		// Don't return an error if there are parse error diagnostics to be shown, but also do not
		// continue since we won't be able to show the vulnerability diagnostics.
		if pm != nil && len(pm.ParseErrors) != 0 {
			return nil, nil
		}
		return nil, err
	}

	fromGovulncheck := true
	vs := snapshot.View().Vulnerabilities(fh.URI())[fh.URI()]
	if vs == nil && snapshot.View().Options().Vulncheck == source.ModeVulncheckImports {
		vs, err = snapshot.ModVuln(ctx, fh.URI())
		if err != nil {
			return nil, err
		}
		fromGovulncheck = false
	}
	if vs == nil || len(vs.Vulns) == 0 {
		return nil, nil
	}

	suggestRunOrResetGovulncheck, err := suggestGovulncheckAction(fromGovulncheck, fh.URI())
	if err != nil {
		// must not happen
		return nil, err // TODO: bug report
	}
	type modVuln struct {
		mod  *govulncheck.Module
		vuln *govulncheck.Vuln
	}
	vulnsByModule := make(map[string][]modVuln)
	for _, vuln := range vs.Vulns {
		for _, mod := range vuln.Modules {
			vulnsByModule[mod.Path] = append(vulnsByModule[mod.Path], modVuln{mod, vuln})
		}
	}

	for _, req := range pm.File.Require {
		vulns := vulnsByModule[req.Mod.Path]
		if len(vulns) == 0 {
			continue
		}
		// note: req.Syntax is the line corresponding to 'require', which means
		// req.Syntax.Start can point to the beginning of the "require" keyword
		// for a single line require (e.g. "require golang.org/x/mod v0.0.0").
		start := req.Syntax.Start.Byte
		if len(req.Syntax.Token) == 3 {
			start += len("require ")
		}
		rng, err := pm.Mapper.OffsetRange(start, req.Syntax.End.Byte)
		if err != nil {
			return nil, err
		}
		// Map affecting vulns to 'warning' level diagnostics,
		// others to 'info' level diagnostics.
		// Fixes will include only the upgrades for warning level diagnostics.
		var warningFixes, infoFixes []source.SuggestedFix
		var warning, info []string
		var relatedInfo []source.RelatedInformation
		for _, mv := range vulns {
			mod, vuln := mv.mod, mv.vuln
			// It is possible that the source code was changed since the last
			// govulncheck run and information in the `vulns` info is stale.
			// For example, imagine that a user is in the middle of updating
			// problematic modules detected by the govulncheck run by applying
			// quick fixes. Stale diagnostics can be confusing and prevent the
			// user from quickly locating the next module to fix.
			// Ideally we should rerun the analysis with the updated module
			// dependencies or any other code changes, but we are not yet
			// in the position of automatically triggerring the analysis
			// (govulncheck can take a while). We also don't know exactly what
			// part of source code was changed since `vulns` was computed.
			// As a heuristic, we assume that a user upgrades the affecting
			// module to the version with the fix or the latest one, and if the
			// version in the require statement is equal to or higher than the
			// fixed version, skip generating a diagnostic about the vulnerability.
			// Eventually, the user has to rerun govulncheck.
			if mod.FixedVersion != "" && semver.IsValid(req.Mod.Version) && semver.Compare(mod.FixedVersion, req.Mod.Version) <= 0 {
				continue
			}
			if !vuln.IsCalled() {
				info = append(info, vuln.OSV.ID)
			} else {
				warning = append(warning, vuln.OSV.ID)
				relatedInfo = append(relatedInfo, listRelatedInfo(ctx, snapshot, vuln)...)
			}
			// Upgrade to the exact version we offer the user, not the most recent.
			if fixedVersion := mod.FixedVersion; semver.IsValid(fixedVersion) && semver.Compare(req.Mod.Version, fixedVersion) < 0 {
				cmd, err := getUpgradeCodeAction(fh, req, fixedVersion)
				if err != nil {
					return nil, err // TODO: bug report
				}
				sf := source.SuggestedFixFromCommand(cmd, protocol.QuickFix)
				if !vuln.IsCalled() {
					infoFixes = append(infoFixes, sf)
				} else {
					warningFixes = append(warningFixes, sf)
				}
			}
		}

		if len(warning) == 0 && len(info) == 0 {
			continue
		}
		// Add an upgrade for module@latest.
		// TODO(suzmue): verify if latest is the same as fixedVersion.
		latest, err := getUpgradeCodeAction(fh, req, "latest")
		if err != nil {
			return nil, err // TODO: bug report
		}
		sf := source.SuggestedFixFromCommand(latest, protocol.QuickFix)
		if len(warningFixes) > 0 {
			warningFixes = append(warningFixes, sf)
		}
		if len(infoFixes) > 0 {
			infoFixes = append(infoFixes, sf)
		}

		sort.Strings(warning)
		sort.Strings(info)

		if len(warning) > 0 {
			warningFixes = append(warningFixes, suggestRunOrResetGovulncheck)
			vulnDiagnostics = append(vulnDiagnostics, &source.Diagnostic{
				URI:            fh.URI(),
				Range:          rng,
				Severity:       protocol.SeverityWarning,
				Source:         source.Vulncheck,
				Message:        getVulnMessage(req.Mod.Path, warning, true, fromGovulncheck),
				SuggestedFixes: warningFixes,
				Related:        relatedInfo,
			})
		}
		if len(info) > 0 {
			infoFixes = append(infoFixes, suggestRunOrResetGovulncheck)
			vulnDiagnostics = append(vulnDiagnostics, &source.Diagnostic{
				URI:            fh.URI(),
				Range:          rng,
				Severity:       protocol.SeverityInformation,
				Source:         source.Vulncheck,
				Message:        getVulnMessage(req.Mod.Path, info, false, fromGovulncheck),
				SuggestedFixes: infoFixes,
				Related:        relatedInfo,
			})
		}
	}

	// TODO(hyangah): place this diagnostic on the `go` directive or `toolchain` directive
	// after https://go.dev/issue/57001.
	const diagnoseStdLib = false
	if diagnoseStdLib {
		// Add standard library vulnerabilities.
		stdlibVulns := vulnsByModule["stdlib"]
		if len(stdlibVulns) == 0 {
			return vulnDiagnostics, nil
		}

		// Put the standard library diagnostic on the module declaration.
		rng, err := pm.Mapper.OffsetRange(pm.File.Module.Syntax.Start.Byte, pm.File.Module.Syntax.End.Byte)
		if err != nil {
			return vulnDiagnostics, nil // TODO: bug report
		}

		stdlib := stdlibVulns[0].mod.FoundVersion
		var warning, info []string
		var relatedInfo []source.RelatedInformation
		for _, mv := range stdlibVulns {
			vuln := mv.vuln
			stdlib = mv.mod.FoundVersion
			if !vuln.IsCalled() {
				info = append(info, vuln.OSV.ID)
			} else {
				warning = append(warning, vuln.OSV.ID)
				relatedInfo = append(relatedInfo, listRelatedInfo(ctx, snapshot, vuln)...)
			}
		}
		if len(warning) > 0 {
			fixes := []source.SuggestedFix{suggestRunOrResetGovulncheck}
			vulnDiagnostics = append(vulnDiagnostics, &source.Diagnostic{
				URI:            fh.URI(),
				Range:          rng,
				Severity:       protocol.SeverityWarning,
				Source:         source.Vulncheck,
				Message:        getVulnMessage(stdlib, warning, true, fromGovulncheck),
				SuggestedFixes: fixes,
				Related:        relatedInfo,
			})
		}
		if len(info) > 0 {
			fixes := []source.SuggestedFix{suggestRunOrResetGovulncheck}
			vulnDiagnostics = append(vulnDiagnostics, &source.Diagnostic{
				URI:            fh.URI(),
				Range:          rng,
				Severity:       protocol.SeverityInformation,
				Source:         source.Vulncheck,
				Message:        getVulnMessage(stdlib, info, false, fromGovulncheck),
				SuggestedFixes: fixes,
				Related:        relatedInfo,
			})
		}
	}

	return vulnDiagnostics, nil
}

// suggestGovulncheckAction returns a code action that suggests either run govulncheck
// for more accurate investigation (if the present vulncheck diagnostics are based on
// analysis less accurate than govulncheck) or reset the existing govulncheck result
// (if the present vulncheck diagnostics are already based on govulncheck run).
func suggestGovulncheckAction(fromGovulncheck bool, uri span.URI) (source.SuggestedFix, error) {
	if fromGovulncheck {
		resetVulncheck, err := command.NewResetGoModDiagnosticsCommand("Reset govulncheck result", command.ResetGoModDiagnosticsArgs{
			URIArg:           command.URIArg{URI: protocol.DocumentURI(uri)},
			DiagnosticSource: string(source.Vulncheck),
		})
		if err != nil {
			return source.SuggestedFix{}, err
		}
		return source.SuggestedFixFromCommand(resetVulncheck, protocol.QuickFix), nil
	}
	vulncheck, err := command.NewRunGovulncheckCommand("Run govulncheck to verify", command.VulncheckArgs{
		URI:     protocol.DocumentURI(uri),
		Pattern: "./...",
	})
	if err != nil {
		return source.SuggestedFix{}, err
	}
	return source.SuggestedFixFromCommand(vulncheck, protocol.QuickFix), nil
}

func getVulnMessage(mod string, vulns []string, used, fromGovulncheck bool) string {
	var b strings.Builder
	if used {
		switch len(vulns) {
		case 1:
			fmt.Fprintf(&b, "%v has a vulnerability used in the code: %v.", mod, vulns[0])
		default:
			fmt.Fprintf(&b, "%v has vulnerabilities used in the code: %v.", mod, strings.Join(vulns, ", "))
		}
	} else {
		if fromGovulncheck {
			switch len(vulns) {
			case 1:
				fmt.Fprintf(&b, "%v has a vulnerability %v that is not used in the code.", mod, vulns[0])
			default:
				fmt.Fprintf(&b, "%v has known vulnerabilities %v that are not used in the code.", mod, strings.Join(vulns, ", "))
			}
		} else {
			switch len(vulns) {
			case 1:
				fmt.Fprintf(&b, "%v has a vulnerability %v.", mod, vulns[0])
			default:
				fmt.Fprintf(&b, "%v has known vulnerabilities %v.", mod, strings.Join(vulns, ", "))
			}
		}
	}
	return b.String()
}

func listRelatedInfo(ctx context.Context, snapshot source.Snapshot, vuln *govulncheck.Vuln) []source.RelatedInformation {
	var ri []source.RelatedInformation
	for _, m := range vuln.Modules {
		for _, p := range m.Packages {
			for _, c := range p.CallStacks {
				if len(c.Frames) == 0 {
					continue
				}
				entry := c.Frames[0]
				pos := entry.Position
				if pos.Filename == "" {
					continue // token.Position Filename is an optional field.
				}
				uri := span.URIFromPath(pos.Filename)
				startPos := protocol.Position{
					Line: uint32(pos.Line) - 1,
					// We need to read the file contents to precisesly map
					// token.Position (pos) to the UTF16-based column offset
					// protocol.Position requires. That can be expensive.
					// We need this related info to just help users to open
					// the entry points of the callstack and once the file is
					// open, we will compute the precise location based on the
					// open file contents. So, use the beginning of the line
					// as the position here instead of precise UTF16-based
					// position computation.
					Character: 0,
				}
				ri = append(ri, source.RelatedInformation{
					URI: uri,
					Range: protocol.Range{
						Start: startPos,
						End:   startPos,
					},
					Message: fmt.Sprintf("[%v] %v -> %v.%v", vuln.OSV.ID, entry.Name(), p.Path, c.Symbol),
				})
			}
		}
	}
	return ri
}

func formatMessage(v *govulncheck.Vuln) string {
	details := []byte(v.OSV.Details)
	// Remove any new lines that are not preceded or followed by a new line.
	for i, r := range details {
		if r == '\n' && i > 0 && details[i-1] != '\n' && i+1 < len(details) && details[i+1] != '\n' {
			details[i] = ' '
		}
	}
	return strings.TrimSpace(strings.Replace(string(details), "\n\n", "\n\n  ", -1))
}

// href returns the url for the vulnerability information.
// Eventually we should retrieve the url embedded in the osv.Entry.
// While vuln.go.dev is under development, this always returns
// the page in pkg.go.dev.
func href(vuln *osv.Entry) string {
	return fmt.Sprintf("https://pkg.go.dev/vuln/%s", vuln.ID)
}

func getUpgradeCodeAction(fh source.FileHandle, req *modfile.Require, version string) (protocol.Command, error) {
	cmd, err := command.NewUpgradeDependencyCommand(upgradeTitle(version), command.DependencyArgs{
		URI:        protocol.URIFromSpanURI(fh.URI()),
		AddRequire: false,
		GoCmdArgs:  []string{req.Mod.Path + "@" + version},
	})
	if err != nil {
		return protocol.Command{}, err
	}
	return cmd, nil
}

func upgradeTitle(fixedVersion string) string {
	title := fmt.Sprintf("%s%v", upgradeCodeActionPrefix, fixedVersion)
	return title
}

// SelectUpgradeCodeActions takes a list of code actions for a required module
// and returns a more selective list of upgrade code actions,
// where the code actions have been deduped. Code actions unrelated to upgrade
// are deduplicated by the name.
func SelectUpgradeCodeActions(actions []protocol.CodeAction) []protocol.CodeAction {
	if len(actions) <= 1 {
		return actions // return early if no sorting necessary
	}
	var others []protocol.CodeAction

	seen := make(map[string]bool)

	set := make(map[string]protocol.CodeAction)
	for _, action := range actions {
		if strings.HasPrefix(action.Title, upgradeCodeActionPrefix) {
			set[action.Command.Title] = action
		} else if !seen[action.Command.Title] {
			seen[action.Command.Title] = true
			others = append(others, action)
		}
	}
	var upgrades []protocol.CodeAction
	for _, action := range set {
		upgrades = append(upgrades, action)
	}
	// Sort results by version number, latest first.
	// There should be no duplicates at this point.
	sort.Slice(upgrades, func(i, j int) bool {
		vi, vj := getUpgradeVersion(upgrades[i]), getUpgradeVersion(upgrades[j])
		return vi == "latest" || (vj != "latest" && semver.Compare(vi, vj) > 0)
	})
	// Choose at most one specific version and the latest.
	if getUpgradeVersion(upgrades[0]) == "latest" {
		return append(upgrades[:2], others...)
	}
	return append(upgrades[:1], others...)
}

func getUpgradeVersion(p protocol.CodeAction) string {
	return strings.TrimPrefix(p.Title, upgradeCodeActionPrefix)
}
