// 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 main

import (
	"context"
	"encoding/json"
	"fmt"
	"path"
	"sort"
	"strings"

	"github.com/go-git/go-git/v5"
	"github.com/go-git/go-git/v5/plumbing/filemode"
	"github.com/go-git/go-git/v5/plumbing/object"
	"golang.org/x/vuln/internal/cveschema"
	"golang.org/x/vuln/internal/derrors"
	"golang.org/x/vuln/internal/gitrepo"
	"golang.org/x/vuln/internal/worker/log"
)

// Run clones the CVEProject/cvelist repository and compares the files to the
// existing triaged-cve-list.
func Run(dirpath string, triaged map[string]string) (err error) {
	defer derrors.Wrap(&err, "Run(triaged)")
	var repo *git.Repository
	if dirpath != "" {
		repo, err = gitrepo.Open(dirpath)
	} else {
		repo, err = gitrepo.Clone(gitrepo.CVElistRepoURL)
	}
	if err != nil {
		return err
	}
	root, err := gitrepo.Root(repo)
	if err != nil {
		return err
	}
	t := newTriager(triaged)
	log.Infof(context.Background(), "Finding new Go vulnerabilities from CVE list...")
	if err := walkRepo(repo, root, "", t); err != nil {
		return err
	}
	var newVulns []string
	for cveID, r := range t {
		if r.isGoVuln {
			newVulns = append(newVulns, fmt.Sprintf("%s (%s)", cveID, r.modulePath))
		}
	}
	sort.Strings(newVulns)
	log.Infof(context.Background(), "Found %d new issues from %d CVEs", t.totalVulns(), t.totalCVEs())
	for _, v := range newVulns {
		fmt.Println(v)
	}
	return nil
}

// walkRepo looks at the files in t, recursively, and check if it is a CVE that
// needs to be manually triaged.
func walkRepo(repo *git.Repository, root *object.Tree, dirpath string, t triager) (err error) {
	defer derrors.Wrap(&err, "walkRepo(repo, root, %q, t)", dirpath)
	for _, e := range root.Entries {
		fp := path.Join(dirpath, e.Name)
		if !strings.HasPrefix(fp, "202") {
			continue
		}
		switch e.Mode {
		case filemode.Dir:
			root2, err := repo.TreeObject(e.Hash)
			if err != nil {
				return err
			}
			if err := walkRepo(repo, root2, fp, t); err != nil {
				return err
			}
		default:
			if !strings.HasPrefix(e.Name, "CVE-") {
				continue
			}
			cveID := strings.TrimSuffix(e.Name, ".json")
			if t.contains(cveID) {
				continue
			}
			c, err := parseCVE(repo, e)
			if err != nil {
				return err
			}
			issue, err := triageCVE(c)
			if err != nil {
				return err
			}
			if issue != nil {
				t.add(issue)
			}
		}
	}
	return nil
}

// parseCVEJSON parses a CVE file following the CVE JSON format:
// https://github.com/CVEProject/automation-working-group/blob/master/cve_json_schema/DRAFT-JSON-file-format-v4.md
func parseCVE(r *git.Repository, e object.TreeEntry) (_ *cveschema.CVE, err error) {
	defer derrors.Wrap(&err, "parseCVE(r, e)")
	blob, err := r.BlobObject(e.Hash)
	if err != nil {
		return nil, fmt.Errorf("r.BlobObject: %v", err)
	}
	src, err := blob.Reader()
	if err != nil {
		return nil, fmt.Errorf("blob.Reader: %v", err)
	}
	defer func() {
		cerr := src.Close()
		if err == nil {
			err = cerr
		}
	}()
	var c cveschema.CVE
	d := json.NewDecoder(src)
	if err := d.Decode(&c); err != nil {
		return nil, fmt.Errorf("d.Decode: %v", err)
	}
	if err != nil {
		return nil, err
	}
	return &c, nil
}
