// Copyright 2024 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 (
	"bytes"
	"compress/gzip"
	"context"
	_ "embed"
	"encoding/csv"
	"fmt"
	"strconv"
	"strings"
	"sync"

	"golang.org/x/vulndb/cmd/vulnreport/log"
	"golang.org/x/vulndb/internal/issues"
)

type triage struct {
	*xrefer
	*issueParser
	*fixer

	mu               sync.Mutex // protects aliasesToIssues and stats
	aliasesToIssues  map[string][]int
	modulesToImports map[string]int
	stats            []issuesList
}

func (*triage) name() string { return "triage" }

func (*triage) usage() (string, string) {
	const desc = "determines priority and finds likely duplicates of the given Github issue (with no args, looks at all open issues)"
	return "<no args> | " + ghIssueArgs, desc
}

func (t *triage) close() error {
	log.Outf("triaged %d issues:%s%s",
		len(t.isses), listItem, strings.Join(toStrings(t.stats), listItem))
	// Print the command to create all high priority reports.
	if len(t.stats[statHighPriority]) > 0 {
		log.Outf("helpful commands:\n  $ vulnreport create %s", t.stats[statHighPriority].issNums())
	}
	return nil
}

func toStrings(stats []issuesList) (strs []string) {
	for i, s := range stats {
		strs = append(strs, fmt.Sprintf("%d %s", len(s), statNames[i]))
	}
	return strs
}

//go:embed data/importers.csv.gz
var importers []byte

func (t *triage) setup(ctx context.Context) error {
	t.aliasesToIssues = make(map[string][]int)
	t.stats = make([]issuesList, len(statNames))
	m, err := gzCSVToMap(importers)
	if err != nil {
		return err
	}
	t.modulesToImports = m

	t.fixer = new(fixer)
	t.issueParser = new(issueParser)
	t.xrefer = new(xrefer)
	return setupAll(ctx, t.fixer, t.issueParser, t.xrefer)
}

func (t *triage) skipReason(iss *issues.Issue) string {
	if iss.HasLabel(labelDirect) {
		return "direct external report"
	}

	if !*force && iss.HasLabel(labelTriaged) {
		return "already triaged (use -f to force re-triage)"
	}

	return t.xrefer.skipReason(iss)
}

func (t *triage) run(ctx context.Context, issNum string) (err error) {
	iss, err := t.lookup(ctx, issNum)
	if err != nil {
		return err
	}

	if reason := t.skipReason(iss); reason != "" {
		t.addStat(iss, statSkipped, reason)
		return nil
	}

	t.triage(ctx, iss)
	return nil
}

type priorityResult struct {
	priority       int
	priorityReason string
	notGo          bool
}

func (t *triage) triage(ctx context.Context, iss *issues.Issue) {
	labels := []string{labelTriaged}
	defer func() {
		if *dry {
			log.Infof("would add labels: [%s]", strings.Join(labels, ", "))
		} else if err := t.ic.AddLabels(ctx, iss.Number, labels); err != nil {
			log.Warnf("could not auto-add label(s) for issue #%d", iss.Number)
		}
	}()

	xrefs := t.findDuplicates(ctx, iss)
	if len(xrefs) != 0 {
		var strs []string
		for ref, aliases := range xrefs {
			strs = append(strs, fmt.Sprintf("#%d shares alias(es) %s with %s", iss.Number, strings.Join(aliases, ", "), ref))
		}
		t.addStat(iss, statDuplicate, strings.Join(strs, listItem))
		labels = append(labels, labelPossibleDuplicate)
	}

	tr := t.priorityOf(iss)
	t.addStat(iss, tr.priority, tr.priorityReason)

	if tr.notGo {
		t.addStat(iss, statNotGo, "more than 20 percent of reports with this module are NOT_GO_CODE")
		labels = append(labels, labelPossiblyNotGo)
	}

	if tr.priority == statHighPriority {
		labels = append(labels, labelHighPriority)
	}
}

func (t *triage) priorityOf(iss *issues.Issue) *priorityResult {
	const highPriority = 100

	mp := t.canonicalModule(modulePath(iss))
	excluded, regular, notGoCode := t.xrefCount(mp)
	// more than 20% of reports are labeled not Go
	possiblyNotGo := excluded != 0 && (float32(notGoCode)/float32(excluded+regular))*100 > 20

	importers, ok := t.modulesToImports[mp]
	if !ok {
		return &priorityResult{
			priority:       statUnknownPriority,
			notGo:          possiblyNotGo,
			priorityReason: fmt.Sprintf("module %s not found", mp),
		}
	}

	priority := statLowPriority
	reason := fmt.Sprintf("%s has %d importers and %d regular vs %d excluded reports", mp, importers, regular, excluded)

	if importers >= highPriority && regular >= excluded {
		priority = statHighPriority
	}

	return &priorityResult{
		priority:       priority,
		notGo:          possiblyNotGo,
		priorityReason: reason,
	}
}

func gzCSVToMap(b []byte) (map[string]int, error) {
	gzr, err := gzip.NewReader(bytes.NewReader(b))
	if err != nil {
		return nil, err
	}

	reader := csv.NewReader(gzr)
	records, err := reader.ReadAll()
	if err != nil {
		return nil, err
	}

	m := make(map[string]int)
	for _, record := range records[1:] {
		if len(record) != 2 {
			continue
		}
		n, err := strconv.Atoi(record[1])
		if err != nil {
			continue
		}
		m[record[0]] = n
	}

	return m, nil
}

func (t *triage) findDuplicates(ctx context.Context, iss *issues.Issue) map[string][]string {
	aliases := aliases(iss)

	if len(aliases) == 0 {
		log.Infof("skipping duplicate search for issue #%d (no aliases found)", iss.Number)
		return nil
	}

	aliases = t.allAliases(ctx, aliases)
	xrefs := make(map[string][]string)
	for _, a := range aliases {
		// Find existing reports with this alias.
		if reports := t.rc.ReportsByAlias(a); len(reports) != 0 {
			for _, r := range reports {
				fname, err := r.YAMLFilename()
				if err != nil {
					fname = r.ID
				}
				xrefs[fname] = append(xrefs[fname], a)
			}
		}

		// Find other issues with this alias.
		// Note: this currently only operates on other issues that have
		// been seen by the triage command, not all issues on the tracker.
		for _, issNum := range t.lookupAlias(a) {
			ref := t.ic.Reference(issNum)
			xrefs[ref] = append(xrefs[ref], a)
		}

		t.addAlias(a, iss.Number)
	}

	return xrefs
}

func (t *triage) lookupAlias(a string) []int {
	t.mu.Lock()
	defer t.mu.Unlock()

	return t.aliasesToIssues[a]
}

func (t *triage) addAlias(a string, n int) {
	t.mu.Lock()
	defer t.mu.Unlock()

	t.aliasesToIssues[a] = append(t.aliasesToIssues[a], n)
}

func (t *triage) addStat(iss *issues.Issue, stat int, reason string) {
	t.mu.Lock()
	defer t.mu.Unlock()

	var lg func(string, ...any)
	switch stat {
	case statLowPriority, statSkipped:
		lg = log.Infof
	case statHighPriority, statDuplicate, statNotGo:
		lg = log.Outf
	case statUnknownPriority:
		lg = log.Warnf
	default:
		panic(fmt.Sprintf("BUG: unknown stat: %d", stat))
	}

	t.stats[stat] = append(t.stats[stat], iss)
	lg("issue %s is %s%s%s", t.ic.Reference(iss.Number), statNames[stat], listItem, reason)
}

const (
	statHighPriority = iota
	statLowPriority
	statUnknownPriority
	statSkipped

	statDuplicate
	statNotGo
)

var statNames = []string{
	statHighPriority:    "high priority",
	statLowPriority:     "low priority",
	statUnknownPriority: "unknown priority",
	statSkipped:         "skipped",
	statDuplicate:       "likely duplicate",
	statNotGo:           "possibly not Go",
}

type issuesList []*issues.Issue

func (i issuesList) issNums() string {
	var is []string
	for _, iss := range i {
		is = append(is, strconv.Itoa(iss.Number))
	}
	return strings.Join(is, " ")
}
