// 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.ExcludedTypes {
		data(string(er), 2, func(s *summary) int { return s.excludedByType[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
	excludedByType                                            map[report.ExcludedType]int
	regularByReview                                           map[report.ReviewStatus]int
}

func newSummary() *summary {
	return &summary{
		excludedByType:  make(map[report.ExcludedType]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.excludedByType[r.Excluded]++

			yearSummary.excluded++
			yearSummary.excludedByType[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
}
