// Copyright 2023 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.

// Command inspect provides insights into the current contents of vulndb.
package main

import (
	"context"
	"flag"
	"fmt"
	"log"
	"os"
	"sort"
	"strconv"
	"strings"
	"text/tabwriter"
	"time"

	"golang.org/x/exp/maps"
	"golang.org/x/vulndb/internal/genericosv"
	"golang.org/x/vulndb/internal/ghsarepo"
	"golang.org/x/vulndb/internal/report"
	"golang.org/x/vulndb/internal/stdlib"
)

var (
	localGHSA = flag.String("local-ghsa", "", "path to local GHSA repo, instead of cloning remote")
	detail    = flag.Bool("detail", false, "if true, print more details on GHSAs not yet in vulndb")
)

func main() {
	start := time.Now()
	flag.Parse()

	ctx := context.Background()
	rc, err := report.NewLocalClient(ctx, ".")
	if err != nil {
		log.Fatal(err)
	}

	var gc *ghsarepo.Client
	if *localGHSA != "" {
		gc, err = ghsarepo.NewLocalClient(ctx, *localGHSA)
		if err != nil {
			log.Fatal(err)
		}
	} else {
		log.Println("cloning remote GHSA repo (use -local-ghsa to speed this up)...")
		gc, err = ghsarepo.NewDefaultClient()
		if err != nil {
			log.Fatal(err)
		}
	}

	overall, byYear := summarize(gc.List(), rc.List())

	display(overall, byYear)
	if *detail {
		fmt.Println("\n=== GHSAs not yet in vulndb ===")
		displayGHSAs(overall.ghsasNotInVDB)
	}

	fmt.Printf("\n%s\n", time.Since(start).Truncate(time.Millisecond))
}

func display(overall *summary, byYear map[int]*summary) {
	tw := tabwriter.NewWriter(os.Stdout, 2, 4, 2, ' ', 0)
	years := maps.Keys(byYear)
	sort.Sort(sort.Reverse(sort.IntSlice(years))) // sort descending

	headings := func() {
		fmt.Fprintf(tw, "\t%s", "Total")
		for _, year := range years {
			fmt.Fprintf(tw, "\t%4d", year)
		}
		fmt.Fprintf(tw, "\n")
		fmt.Fprintf(tw, "\t%s", "-----")
		for range years {
			fmt.Fprintf(tw, "\t%4s", "----")
		}
		fmt.Fprintf(tw, "\n")
	}
	data := func(desc string, indent int, getData func(s *summary) int) {
		var indentS string
		if indent > 0 {
			indentS = strings.Repeat("--", indent) + " "
		}
		fmt.Fprintf(tw, "%s%s\t%4d", indentS, desc, getData(overall))
		for _, year := range years {
			fmt.Fprintf(tw, "\t%4d", getData(byYear[year]))
		}
		fmt.Fprintf(tw, "\n")
	}
	newline := func() {
		fmt.Fprintf(tw, "%s\n", strings.Repeat("\t", len(years))) // preserve tab formatting
	}

	// Summary of Go reports by year.
	headings()
	data("Go reports", 0, func(s *summary) int { return s.reports })
	data("Regular reports", 1, func(s *summary) int { return s.regular })
	for _, rs := range []report.ReviewStatus{report.Reviewed, report.Unreviewed} {
		data(rs.String(), 2, func(s *summary) int { return s.regularByReview[rs] })
	}
	data("Withdrawn reports", 1, func(s *summary) int { return s.withdrawn })
	data("Excluded reports", 1, func(s *summary) int { return s.excluded })
	for _, er := range report.ExcludedReasons {
		data(string(er), 2, func(s *summary) int { return s.excludedByReason[er] })
	}
	data("Reports with no GHSA (+)", 1, func(s *summary) int { return s.noGHSA })
	data("Stdlib, toolchain and x/ reports", 1, func(s *summary) int { return s.firstParty })

	// Summary of GHSAs by year.
	newline()
	headings()
	data("GHSAs affecting Go", 0, func(s *summary) int { return s.ghsas })
	data("GHSAs not yet in vulndb (++)", 1, func(s *summary) int { return len(s.ghsasNotInVDB) })

	// Additional context.
	newline()
	fmt.Fprintln(tw, "(+) \"Go reports with no GHSA\" are published third-party Go reports\nwith no corresponding GHSA. (This isn't a problem; it's informational only.)")
	fmt.Fprintln(tw, "(++) \"GHSAs not yet in vulndb\" are published GHSAs with no corresponding\nGo report. There may already be an open issue on the tracker for these.")

	tw.Flush()
}

func displayGHSAs(ghsas []string) {
	for i, g := range ghsas {
		fmt.Println()
		fmt.Printf("%d) %s\n", i+1, g)
		fmt.Printf("https://github.com/advisories/%s\n", g)
		fmt.Printf("search issue tracker: https://github.com/golang/vulndb/issues?q=is%%3Aissue+%s\n", g)
	}
}

type summary struct {
	reports, regular, withdrawn, excluded, noGHSA, firstParty int
	ghsas                                                     int
	ghsasNotInVDB                                             []string
	excludedByReason                                          map[report.ExcludedReason]int
	regularByReview                                           map[report.ReviewStatus]int
}

func newSummary() *summary {
	return &summary{
		excludedByReason: make(map[report.ExcludedReason]int),
		regularByReview:  make(map[report.ReviewStatus]int),
	}
}

func summarize(ghsas []*genericosv.Entry, reports []*report.Report) (*summary, map[int]*summary) {
	overall := newSummary()
	byYear := make(map[int]*summary)

	ghsasWithReport := make(map[string]bool)
	for _, r := range reports {
		year, err := strconv.Atoi(strings.Split(r.ID, "-")[1])
		if err != nil {
			panic(err)
		}
		if _, ok := byYear[year]; !ok {
			byYear[year] = newSummary()
		}
		yearSummary := byYear[year]

		overall.reports++
		yearSummary.reports++

		if isFirstParty(r) {
			overall.firstParty++
			yearSummary.firstParty++
		}

		if r.IsExcluded() {
			overall.excluded++
			overall.excludedByReason[r.Excluded]++

			yearSummary.excluded++
			yearSummary.excludedByReason[r.Excluded]++
		} else if r.Withdrawn != nil {
			overall.withdrawn++
			yearSummary.withdrawn++
		} else {
			overall.regular++
			yearSummary.regular++

			overall.regularByReview[r.ReviewStatus]++
			yearSummary.regularByReview[r.ReviewStatus]++
		}

		if len(r.GHSAs) == 0 && r.CVEMetadata == nil {
			overall.noGHSA++
			yearSummary.noGHSA++
		}
		for _, ghsa := range r.GHSAs {
			ghsasWithReport[ghsa] = true
		}
	}

	for _, ghsa := range ghsas {
		year := ghsa.Published.Year()
		if _, ok := byYear[year]; !ok {
			byYear[year] = newSummary()
		}
		yearSummary := byYear[year]
		overall.ghsas++
		yearSummary.ghsas++
		if _, ok := ghsasWithReport[ghsa.ID]; !ok {
			overall.ghsasNotInVDB = append(overall.ghsasNotInVDB, ghsa.ID)
			yearSummary.ghsasNotInVDB = append(yearSummary.ghsasNotInVDB, ghsa.ID)
		}
	}

	return overall, byYear
}

func isFirstParty(r *report.Report) bool {
	for _, m := range r.Modules {
		if stdlib.IsStdModule(m.Module) || stdlib.IsCmdModule(m.Module) || stdlib.IsXModule(m.Module) {
			return true
		}
	}
	return false
}
