// Copyright 2022 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 worker

import (
	"archive/zip"
	"context"
	"errors"
	"fmt"
	"io"
	"os"
	"path/filepath"
	"sort"
	"strings"
	"time"

	"cloud.google.com/go/storage"
	"golang.org/x/exp/vulncheck"
	"golang.org/x/tools/go/packages"
	vulnc "golang.org/x/vuln/client"
	"golang.org/x/vulndb/internal/derrors"
	"golang.org/x/vulndb/internal/worker/log"
	"golang.org/x/vulndb/internal/worker/store"
)

// Selected repos under golang.org/x.
var modulesToScan = []string{
	"golang.org/x/build", "golang.org/x/crypto", "golang.org/x/exp/event", "golang.org/x/exp/vulncheck",
	"golang.org/x/image", "golang.org/x/mod", "golang.org/x/net", "golang.org/x/oauth2",
	//"golang.org/x/pkgsite", requires 1.18-aware tools
	"golang.org/x/playground", "golang.org/x/review", "golang.org/x/sync",
	"golang.org/x/sys", "golang.org/x/term", "golang.org/x/text", "golang.org/x/time",
	"golang.org/x/tools",
	// "golang.org/x/tools/gopls", requires 1.18-aware tools
	"golang.org/x/vuln", "golang.org/x/vulndb", "golang.org/x/website",
}

type scanError struct {
	err error
}

func (s scanError) Error() string {
	return s.err.Error()
}

func (s scanError) Unwrap() error {
	return s.err
}

// ScanModules scans a list of Go modules for vulnerabilities.
// It assumes the root of each repo is a module, and there are no nested modules.
func ScanModules(ctx context.Context, st store.Store, force bool) error {
	dbClient, err := vulnc.NewClient([]string{vulnDBURL}, vulnc.Options{})
	if err != nil {
		return err
	}
	for _, modulePath := range modulesToScan {
		// Scan the latest version, and the latest tagged version (if they differ).
		latest, err := latestVersion(ctx, modulePath)
		if err != nil {
			return err
		}
		if err := processModule(ctx, modulePath, latest, dbClient, st, force); err != nil {
			if errors.As(err, new(scanError)) {
				return err
			}
			// Otherwise, if the error was in the scanning itself, keep going.
		}
		latestTagged, err := latestTaggedVersion(ctx, modulePath)
		if err != nil {
			return err
		}
		if latestTagged != "" && latestTagged != latest {
			if err := processModule(ctx, modulePath, latestTagged, dbClient, st, force); err != nil {
				return err
			}
		}
	}
	return nil
}

func processModule(ctx context.Context, modulePath, version string, dbClient vulnc.Client, st store.Store, force bool) (err error) {
	defer derrors.Wrap(&err, "processModule(%q, %q)", modulePath, version)

	dbTime, err := vulnDBTime(ctx)
	if err != nil {
		return err
	}
	if !force {
		r, err := st.GetModuleScanRecord(ctx, modulePath, version, dbTime)
		if err != nil {
			return err
		}
		if r != nil {
			// Already done.
			log.Infof(ctx, "already scanned %s@%s at DB time %s", modulePath, version, dbTime)
			return nil
		}
	}
	res, err := scanModule(ctx, modulePath, version, dbClient)
	if err2 := createModuleScanRecord(ctx, st, modulePath, version, dbTime, res, err); err2 != nil {
		return err2
	}
	if err != nil {
		return scanError{err}
	}
	for _, v := range res.Vulns {
		log.Warningf(ctx, "module %s@%s is vulnerable to %s: package %s, symbol %s",
			modulePath, version, v.OSV.ID, v.PkgPath, v.Symbol)
	}
	return nil
}

func createModuleScanRecord(ctx context.Context, st store.Store, path, version string, dbTime time.Time, res *vulncheck.Result, err error) error {
	var errstr string
	var vulnIDs []string
	if err != nil {
		errstr = err.Error()
	} else {
		m := map[string]bool{}
		for _, v := range res.Vulns {
			m[v.OSV.ID] = true
		}
		for id := range m {
			vulnIDs = append(vulnIDs, id)
		}
		sort.Strings(vulnIDs)
	}

	return st.CreateModuleScanRecord(ctx, &store.ModuleScanRecord{
		Path:       path,
		Version:    version,
		DBTime:     dbTime,
		Error:      errstr,
		VulnIDs:    vulnIDs,
		FinishedAt: time.Now(),
	})
}

// scanRepo clones the given repo and analyzes it for vulnerabilities. If commit
// is "HEAD", the head commit is scanned. Otherwise, commit must be a hex string
// corresponding to a commit, and that commit is checked out and scanned.
func scanModule(ctx context.Context, modulePath, version string, dbClient vulnc.Client) (_ *vulncheck.Result, err error) {
	defer derrors.Wrap(&err, "scanModule(%q, %q)", modulePath, version)

	start := time.Now()
	defer func() { log.Infof(ctx, "scanned %s@%s in %.1fs", modulePath, version, time.Since(start).Seconds()) }()

	dir, err := os.MkdirTemp("", "scanModule")
	if err != nil {
		return nil, err
	}

	defer func() {
		err1 := os.RemoveAll(dir)
		if err == nil {
			err = err1
		}
	}()

	zipr, err := moduleZip(ctx, modulePath, version)
	if err != nil {
		return nil, err
	}
	if err := writeZip(zipr, dir, modulePath+"@"+version+"/"); err != nil {
		return nil, err
	}

	cfg := &packages.Config{
		Mode:  packages.NeedName | packages.NeedFiles | packages.NeedCompiledGoFiles | packages.NeedImports | packages.NeedTypes | packages.NeedTypesSizes | packages.NeedSyntax | packages.NeedTypesInfo | packages.NeedDeps | packages.NeedModule,
		Tests: true,
		Dir:   dir, // filepath.Join(dir, modulePath+"@"+version,
	}
	pkgs, err := loadPackages(cfg, []string{"./..."})
	if err != nil {
		return nil, err
	}
	vcfg := &vulncheck.Config{Client: dbClient}
	return vulncheck.Source(ctx, vulncheck.Convert(pkgs), vcfg)
}

func loadPackages(cfg *packages.Config, patterns []string) ([]*packages.Package, error) {
	pkgs, err := packages.Load(cfg, patterns...)
	if err != nil {
		return nil, err
	}
	if packages.PrintErrors(pkgs) > 0 {
		return nil, fmt.Errorf("packages contain errors")
	}
	return pkgs, nil
}

func writeZip(r *zip.Reader, destination, stripPrefix string) error {
	for _, f := range r.File {
		name := strings.TrimPrefix(f.Name, stripPrefix)
		fpath := filepath.Join(destination, name)
		if !strings.HasPrefix(fpath, filepath.Clean(destination)+string(os.PathSeparator)) {
			return fmt.Errorf("%s is an illegal filepath", fpath)
		}
		if f.FileInfo().IsDir() {
			os.MkdirAll(fpath, os.ModePerm)
			continue
		}
		if err := os.MkdirAll(filepath.Dir(fpath), os.ModePerm); err != nil {
			return err
		}
		outFile, err := os.OpenFile(fpath, os.O_WRONLY|os.O_CREATE|os.O_TRUNC, f.Mode())
		if err != nil {
			return err
		}
		rc, err := f.Open()
		if err != nil {
			return err
		}
		if _, err := io.Copy(outFile, rc); err != nil {
			return err
		}
		if err := outFile.Close(); err != nil {
			return err
		}
		if err := rc.Close(); err != nil {
			return err
		}
	}
	return nil
}

// vulnDBTime returns the time that the vuln DB was last updated.
func vulnDBTime(ctx context.Context) (_ time.Time, err error) {
	// Until the vuln DB client supports this, use the update time
	// of the index file.
	defer derrors.Wrap(&err, "vulnDBTime")
	c, err := storage.NewClient(ctx)
	if err != nil {
		return time.Time{}, err
	}
	attrs, err := c.Bucket(vulnDBBucket).Object("index.json").Attrs(ctx)
	if err != nil {
		return time.Time{}, err
	}
	return attrs.Updated, nil
}
