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

import (
	"fmt"
	"go/token"
	"sort"
	"strings"

	"golang.org/x/vuln/internal"
	"golang.org/x/vuln/internal/govulncheck"
	"golang.org/x/vuln/internal/osv"
)

type summaries struct {
	Affected        []vulnSummary `json:"affected,omitempty"`
	Unaffected      []vulnSummary `json:"unaffected,omitempty"`
	AffectedModules int           `json:"affected_modules,omitempty"`
	StdlibAffected  bool          `json:"stdlib_affected,omitempty"`
}

type vulnSummary struct {
	OSV      string
	Details  string
	Modules  []*moduleSummary
	Affected bool
}

type moduleSummary struct {
	IsStd        bool
	Module       string
	FoundVersion string
	FixedVersion string
	Platforms    []string
	Traces       []traceSummary
}

type traceSummary struct {
	Symbol  string
	Compact string
	Trace   []frameSummary
}

type frameSummary struct {
	Symbol   string
	Name     string
	Position string
}

func createSummaries(osvs []*osv.Entry, findings []*govulncheck.Finding) summaries {
	s := summaries{}
	// group findings by osv
	grouped := map[string][]*govulncheck.Finding{}
	var osvids []string
	for _, f := range findings {
		list, found := grouped[f.OSV]
		if !found {
			osvids = append(osvids, f.OSV)
		}
		grouped[f.OSV] = append(list, f)
	}
	// unaffected are (imported) OSVs none of
	// which vulnerabilities are called.
	for _, osvid := range osvids {
		list := grouped[osvid]
		entry := createVulnSummary(osvs, osvid, list)
		if entry.Affected {
			s.Affected = append(s.Affected, entry)
		} else {
			s.Unaffected = append(s.Unaffected, entry)
		}
	}
	mods := make(map[string]struct{})
	for _, a := range s.Affected {
		for _, m := range a.Modules {
			if m.IsStd {
				s.StdlibAffected = true
			} else {
				mods[m.Module] = struct{}{}
			}
		}
	}
	s.AffectedModules = len(mods)
	return s
}

func createVulnSummary(osvs []*osv.Entry, osvid string, findings []*govulncheck.Finding) vulnSummary {
	seen := map[string]struct{}{}
	vInfo := vulnSummary{
		Affected: IsCalled(findings),
		OSV:      osvid,
	}
	osv := findOSV(osvs, osvid)
	if osv != nil {
		vInfo.Details = osv.Details
	}
	for _, f := range findings {
		lastFrame := f.Trace[0]
		// find the right module summary, or create it if this is the first stack for that module
		var ms *moduleSummary
		for _, check := range vInfo.Modules {
			if check.Module == lastFrame.Module {
				ms = check
				break
			}
		}
		if ms == nil {
			ms = &moduleSummary{
				IsStd:        lastFrame.Module == internal.GoStdModulePath,
				Module:       lastFrame.Module,
				FoundVersion: moduleVersionString(lastFrame.Module, lastFrame.Package, lastFrame.Version),
				FixedVersion: moduleVersionString(lastFrame.Module, lastFrame.Package, f.FixedVersion),
				Platforms:    platforms(lastFrame.Module, osv),
			}
			vInfo.Modules = append(vInfo.Modules, ms)
		}
		css := newTraceSummary(f)
		if css.Compact == "" {
			continue
		}
		// Suppress duplicate compact call stack summaries.
		// Note that different call stacks can yield same summaries.
		if _, wasSeen := seen[css.Compact]; !wasSeen {
			seen[css.Compact] = struct{}{}
			ms.Traces = append(ms.Traces, css)
		}
	}
	return vInfo
}

func findOSV(osvs []*osv.Entry, id string) *osv.Entry {
	for _, entry := range osvs {
		if entry.ID == id {
			return entry
		}
	}
	return nil
}

func newTraceSummary(f *govulncheck.Finding) traceSummary {
	css := traceSummary{
		Compact: summarizeTrace(f),
	}
	if len(f.Trace) == 1 && f.Trace[0].Function == "" {
		return css
	}
	for i := len(f.Trace) - 1; i >= 0; i-- {
		frame := f.Trace[i]
		symbol := frame.Function
		if frame.Receiver != "" {
			symbol = fmt.Sprint(frame.Receiver, ".", symbol)
		}
		buf := &strings.Builder{}
		addSymbolName(buf, frame)
		css.Trace = append(css.Trace, frameSummary{
			Symbol:   symbol,
			Name:     buf.String(),
			Position: posToString(frame.Position),
		})
	}
	css.Symbol = css.Trace[len(css.Trace)-1].Symbol
	return css
}

// platforms returns a string describing the GOOS, GOARCH,
// or GOOS/GOARCH pairs that the vuln affects for a particular
// module mod. If it affects all of them, it returns the empty
// string.
//
// When mod is an empty string, returns platform information for
// all modules of e.
func platforms(mod string, e *osv.Entry) []string {
	if e == nil {
		return nil
	}
	platforms := map[string]bool{}
	for _, a := range e.Affected {
		if mod != "" && a.Module.Path != mod {
			continue
		}
		for _, p := range a.EcosystemSpecific.Packages {
			for _, os := range p.GOOS {
				// In case there are no specific architectures,
				// just list the os entries.
				if len(p.GOARCH) == 0 {
					platforms[os] = true
					continue
				}
				// Otherwise, list all the os+arch combinations.
				for _, arch := range p.GOARCH {
					platforms[os+"/"+arch] = true
				}
			}
			// Cover the case where there are no specific
			// operating systems listed.
			if len(p.GOOS) == 0 {
				for _, arch := range p.GOARCH {
					platforms[arch] = true
				}
			}
		}
	}
	var keys []string
	for k := range platforms {
		keys = append(keys, k)
	}
	sort.Strings(keys)
	return keys
}

func posToString(p *govulncheck.Position) string {
	if p == nil || p.Line <= 0 {
		return ""
	}
	return token.Position{
		Filename: AbsRelShorter(p.Filename),
		Offset:   p.Offset,
		Line:     p.Line,
		Column:   p.Column,
	}.String()
}

// wrap wraps s to fit in maxWidth by breaking it into lines at whitespace. If a
// single word is longer than maxWidth, it is retained as its own line.
func wrap(s string, maxWidth int) string {
	var b strings.Builder
	w := 0

	for _, f := range strings.Fields(s) {
		if w > 0 && w+len(f)+1 > maxWidth {
			b.WriteByte('\n')
			w = 0
		}
		if w != 0 {
			b.WriteByte(' ')
			w++
		}
		b.WriteString(f)
		w += len(f)
	}
	return b.String()
}
