// Copyright 2021 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 report

import (
	"errors"
	"fmt"
	"io/ioutil"
	"net/http"
	"os"
	"regexp"
	"strings"

	"golang.org/x/mod/modfile"
	"golang.org/x/mod/module"
	"golang.org/x/mod/semver"
	"golang.org/x/vulndb/internal/derrors"
)

// TODO: getting things from the proxy should all be cached so we
// aren't re-requesting the same stuff over and over.

var proxyURL = "https://proxy.golang.org"

func init() {
	if proxy, ok := os.LookupEnv("GOPROXY"); ok {
		proxyURL = proxy
	}
}

func getModVersions(module string) (_ map[string]bool, err error) {
	defer derrors.Wrap(&err, "getModVersions(%q)", module)
	resp, err := http.Get(fmt.Sprintf("%s/%s/@v/list", proxyURL, module))
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()
	b, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return nil, err
	}
	versions := map[string]bool{}
	for _, v := range strings.Split(string(b), "\n") {
		versions[v] = true
	}
	return versions, nil
}

func getCanonicalModName(module string, version string) (_ string, err error) {
	defer derrors.Wrap(&err, "getCanonicalModName(%q, %q)", module, version)
	resp, err := http.Get(fmt.Sprintf("%s/%s/@v/%s.mod", proxyURL, module, version))
	if err != nil {
		return "", err
	}
	defer resp.Body.Close()
	b, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return "", err
	}
	m, err := modfile.ParseLax("go.mod", b, nil)
	if err != nil {
		return "", err
	}
	if m.Module == nil {
		return "", fmt.Errorf("unable to retrieve module information for %s", module)
	}
	return m.Module.Mod.Path, nil
}

var pseudoVersionRE = regexp.MustCompile(`^v[0-9]+\.(0\.0-|\d+\.\d+-([^+]*\.)?0\.)\d{14}-[A-Za-z0-9]+(\+[0-9A-Za-z-]+(\.[0-9A-Za-z-]+)*)?$`)

// isPseudoVersion reports whether v is a pseudo-version.
// NOTE: this is taken from cmd/go/internal/modfetch/pseudo.go but
// uses regexp instead of the internal lazyregex package.
func isPseudoVersion(v string) bool {
	return strings.Count(v, "-") >= 2 && semver.IsValid(v) && pseudoVersionRE.MatchString(v)
}

func versionExists(version string, versions map[string]bool) (err error) {
	defer derrors.Wrap(&err, "versionExists(%q, %v)", version, versions)
	// TODO: for now, just skip pseudo-versions. at some point we should verify that
	// it is a likely pseudo-version, i.e. one that could feasibly exist given the
	// actual versions that we know about.
	//
	// pseudo-version check should take into account the canonical import path
	// probably? (I think cmd/go/internal/modfetch/coderepo.go has something like
	// this, check the error containing "has post-%v module path")
	if isPseudoVersion(version) {
		return nil
	}
	if !versions[version] {
		return fmt.Errorf("proxy unaware of version")
	}
	return nil
}

func checkModVersions(path string, vr []VersionRange) (err error) {
	defer derrors.Wrap(&err, "checkModVersions(%q, vr)", path)
	realVersions, err := getModVersions(path)
	if err != nil {
		return fmt.Errorf("unable to retrieve module versions from proxy: %s", err)
	}
	checkVersion := func(version string) error {
		if !semver.IsValid(version) {
			return errors.New("invalid module semver")
		}
		if err := module.Check(path, version); err != nil {
			return err
		}
		if err := versionExists(version, realVersions); err != nil {
			return err
		}
		canonicalPath, err := getCanonicalModName(path, version)
		if err != nil {
			return err
		}
		if canonicalPath != path {
			return fmt.Errorf("invalid module path at version (canonical path is %s)", canonicalPath)
		}
		return nil
	}
	for _, version := range vr {
		if version.Introduced != "" {
			if err := checkVersion(version.Introduced); err != nil {
				return fmt.Errorf("bad version.introduced %q: %s", version.Introduced, err)
			}
		}
		if version.Fixed != "" {
			if err := checkVersion(version.Fixed); err != nil {
				return fmt.Errorf("bad version.fixed %q: %s", version.Fixed, err)
			}
		}
	}
	return nil
}

var cveRegex = regexp.MustCompile(`^CVE-\d{4}-\d{4,}$`)

// Lint checks the content of a Report.
// TODO: instead of returning a single error we may want to return a slice, so that
// we aren't fixing one thing at a time. Similarly it might make sense to include
// warnings or informational things alongside errors, especially during for use
// during the triage process.
func (vuln *Report) Lint() []string {
	var issues []string

	var importPath string
	if !vuln.Stdlib {
		if vuln.Module == "" {
			issues = append(issues, "missing module")
		}
		if vuln.Module != "" && vuln.Package == vuln.Module {
			issues = append(issues, "package is redundant and can be removed")
		}
		if vuln.Package != "" && !strings.HasPrefix(vuln.Package, vuln.Module) {
			issues = append(issues, "module must be a prefix of package")
		}
		if vuln.Package == "" {
			importPath = vuln.Module
		} else {
			importPath = vuln.Package
		}
		if vuln.Module != "" && importPath != "" {
			if err := checkModVersions(vuln.Module, vuln.Versions); err != nil {
				issues = append(issues, err.Error())
			}

			if err := module.CheckImportPath(importPath); err != nil {
				issues = append(issues, err.Error())
			}
		}
	} else if vuln.Package == "" {
		issues = append(issues, "missing package")
	}

	for _, additionalPackage := range vuln.AdditionalPackages {
		var additionalImportPath string
		if additionalPackage.Module == "" {
			issues = append(issues, "missing additional_package.module")
		}
		if additionalPackage.Package == additionalPackage.Module {
			issues = append(issues, "package is redundant and can be removed")
		}
		if additionalPackage.Package != "" && !strings.HasPrefix(additionalPackage.Package, additionalPackage.Module) {
			issues = append(issues, "additional_package.module must be a prefix of additional_package.package")
		}
		if additionalPackage.Package == "" {
			additionalImportPath = additionalPackage.Module
		} else {
			additionalImportPath = additionalPackage.Package
		}
		if err := module.CheckImportPath(additionalImportPath); err != nil {
			issues = append(issues, err.Error())
		}
		if !vuln.Stdlib {
			if err := checkModVersions(additionalPackage.Module, additionalPackage.Versions); err != nil {
				issues = append(issues, err.Error())
			}
		}
	}

	if vuln.Description == "" {
		issues = append(issues, "missing description")
	}

	if vuln.Published.IsZero() {
		issues = append(issues, "missing published")
	}

	if vuln.LastModified != nil && vuln.LastModified.Before(vuln.Published) {
		issues = append(issues, "last_modified is before published")
	}

	if vuln.CVE != "" && vuln.CVEMetadata != nil && vuln.CVEMetadata.ID != "" {
		// TODO: may just want to use one of these? :shrug:
		issues = append(issues, "only one of cve and cve_metadata.id should be present")
	}

	if vuln.CVE != "" && !cveRegex.MatchString(vuln.CVE) {
		issues = append(issues, "malformed cve identifier")
	}

	if vuln.CVEMetadata != nil {
		if vuln.CVEMetadata.ID == "" {
			issues = append(issues, "cve_metadata.id is required")
		}
		if !cveRegex.MatchString(vuln.CVEMetadata.ID) {
			issues = append(issues, "malformed cve_metadata.id identifier")
		}
	}

	return issues
}
