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

import (
	"context"
	"fmt"
	"go/token"
	"io"
	"sort"

	"golang.org/x/vuln/internal/result"
	"golang.org/x/vuln/internal/vulncheck"
	"golang.org/x/vuln/osv"
)

// Source reports vulnerabilities that affect the analyzed packages.
//
// Vulnerabilities can be called (affecting the package, because a vulnerable
// symbol is actually exercised) or just imported by the package
// (likely having a non-affecting outcome).
//
// This function is used for source code analysis by cmd/govulncheck and
// exp/govulncheck.
func Source(ctx context.Context, cfg *Config, pkgs []*vulncheck.Package) (*result.Result, error) {
	vcfg := &vulncheck.Config{
		Client:          cfg.Client,
		SourceGoVersion: cfg.GoVersion,
	}
	vr, err := vulncheck.Source(ctx, pkgs, vcfg)
	if err != nil {
		return nil, err
	}
	return createSourceResult(vr, pkgs), nil
}

// Binary detects presence of vulnerable symbols in exe.
//
// This function is used for binary analysis by cmd/govulncheck.
func Binary(ctx context.Context, cfg *Config, exe io.ReaderAt) (*result.Result, error) {
	vcfg := &vulncheck.Config{
		Client: cfg.Client,
	}
	vr, err := binary(ctx, exe, vcfg)
	if err != nil {
		return nil, err
	}
	return createBinaryResult(vr), nil
}

func createSourceResult(vr *vulncheck.Result, pkgs []*vulncheck.Package) *result.Result {
	topPkgs := map[string]bool{}
	for _, p := range pkgs {
		topPkgs[p.PkgPath] = true
	}
	modVersions := moduleVersionMap(vr.Modules)
	callStacks := vulncheck.CallStacks(vr)

	type key struct {
		id  string
		pkg string
		mod string
	}
	// Collect all called symbols for a package.
	// Needed for creating unique call stacks.
	vulnsPerPkg := make(map[key][]*vulncheck.Vuln)
	for _, vv := range vr.Vulns {
		if vv.CallSink != 0 {
			k := key{id: vv.OSV.ID, pkg: vv.PkgPath, mod: vv.ModPath}
			vulnsPerPkg[k] = append(vulnsPerPkg[k], vv)
		}
	}

	// Create Result where each vulncheck.Vuln{OSV, ModPath, PkgPath} becomes
	// a separate Vuln{OSV, Modules{Packages{PkgPath}}} entry. We merge the
	// results later.
	r := &result.Result{}
	for _, vv := range vr.Vulns {
		p := &result.Package{Path: vv.PkgPath}
		m := &result.Module{
			Path:         vv.ModPath,
			FoundVersion: foundVersion(vv.ModPath, modVersions),
			FixedVersion: fixedVersion(vv.ModPath, vv.OSV.Affected),
			Packages:     []*result.Package{p},
		}
		v := &result.Vuln{OSV: vv.OSV, Modules: []*result.Module{m}}

		if vv.CallSink != 0 {
			k := key{id: vv.OSV.ID, pkg: vv.PkgPath, mod: vv.ModPath}
			vcs := uniqueCallStack(vv, callStacks[vv], vulnsPerPkg[k], vr)
			if vcs != nil {
				cs := result.CallStack{
					Frames: stackFramesfromEntries(vcs),
					Symbol: vv.Symbol,
				}
				cs.Summary = summarizeCallStack(cs, topPkgs, p.Path)
				p.CallStacks = []result.CallStack{cs}
			}
		}
		r.Vulns = append(r.Vulns, v)
	}

	r = merge(r)
	sortResult(r)
	return r
}

func createBinaryResult(vr *vulncheck.Result) *result.Result {
	modVersions := moduleVersionMap(vr.Modules)
	// Create Result where each vulncheck.Vuln{OSV, ModPath, PkgPath} becomes
	// a separate Vuln{OSV, Modules{Packages{PkgPath}}} entry. We merge the
	// results later.
	r := &result.Result{}
	for _, vv := range vr.Vulns {
		p := &result.Package{Path: vv.PkgPath}
		// in binary mode, call stacks contain just the symbol data
		p.CallStacks = []result.CallStack{{Symbol: vv.Symbol}}
		m := &result.Module{
			Path:         vv.ModPath,
			FoundVersion: foundVersion(vv.ModPath, modVersions),
			FixedVersion: fixedVersion(vv.ModPath, vv.OSV.Affected),
			Packages:     []*result.Package{p},
		}
		v := &result.Vuln{OSV: vv.OSV, Modules: []*result.Module{m}}
		r.Vulns = append(r.Vulns, v)
	}

	r = merge(r)
	sortResult(r)
	return r
}

// merge takes r and creates a Result where duplicate
// vulns, modules, and packages are merged together.
// For instance, Vulns with the same OSV field are
// merged into a single one. The same applies for
// Modules of a Vuln, and Packages of a Module.
func merge(r *result.Result) *result.Result {
	nr := &result.Result{}
	// merge vulns by their ID. Note that there can
	// be several OSVs with the same ID but different
	// pointer values
	osvs := make(map[string]*osv.Entry)
	vs := make(map[string][]*result.Module)
	for _, v := range r.Vulns {
		osvs[v.OSV.ID] = v.OSV
		vs[v.OSV.ID] = append(vs[v.OSV.ID], v.Modules...)
	}

	for id, mods := range vs {
		v := &result.Vuln{OSV: osvs[id], Modules: mods}
		nr.Vulns = append(nr.Vulns, v)
	}

	// merge modules
	for _, v := range nr.Vulns {
		ms := make(map[string][]*result.Module)
		for _, m := range v.Modules {
			ms[m.Path] = append(ms[m.Path], m)
		}

		var nms []*result.Module
		for mpath, mods := range ms {
			// modules with the same path must have
			// same found and fixed versions
			validateModuleVersions(mods)
			nm := &result.Module{
				Path:         mpath,
				FixedVersion: mods[0].FixedVersion,
				FoundVersion: mods[0].FoundVersion,
			}
			for _, mod := range mods {
				nm.Packages = append(nm.Packages, mod.Packages...)
			}
			nms = append(nms, nm)
		}
		v.Modules = nms
	}

	// merge packages
	for _, v := range nr.Vulns {
		for _, m := range v.Modules {
			ps := make(map[string][]*result.Package)
			for _, p := range m.Packages {
				ps[p.Path] = append(ps[p.Path], p)
			}

			var nps []*result.Package
			for ppath, pkgs := range ps {
				np := &result.Package{Path: ppath}
				for _, p := range pkgs {
					np.CallStacks = append(np.CallStacks, p.CallStacks...)
				}
				nps = append(nps, np)
			}
			m.Packages = nps
		}
	}
	return nr
}

// validateModuleVersions checks that all modules have
// the same found and fixed version. If not, panics.
func validateModuleVersions(modules []*result.Module) {
	var found, fixed string
	for i, m := range modules {
		if i == 0 {
			found = m.FoundVersion
			fixed = m.FixedVersion
			continue
		}
		if m.FoundVersion != found || m.FixedVersion != fixed {
			panic(fmt.Sprintf("found or fixed version incompatible for module %s", m.Path))
		}
	}
}

// sortResults sorts Vulns, Modules, and Packages of r.
func sortResult(r *result.Result) {
	sort.Slice(r.Vulns, func(i, j int) bool {
		return r.Vulns[i].OSV.ID > r.Vulns[j].OSV.ID
	})
	for _, v := range r.Vulns {
		sort.Slice(v.Modules, func(i, j int) bool {
			return v.Modules[i].Path < v.Modules[j].Path
		})
		for _, m := range v.Modules {
			sort.Slice(m.Packages, func(i, j int) bool {
				return m.Packages[i].Path < m.Packages[j].Path
			})
		}
	}
}

// stackFramesFromEntries creates a sequence of stack
// frames from vcs. Position of a StackFrame is the
// call position of the corresponding stack entry.
func stackFramesfromEntries(vcs vulncheck.CallStack) []*result.StackFrame {
	var frames []*result.StackFrame
	for _, e := range vcs {
		fr := &result.StackFrame{
			FuncName: e.Function.Name,
			PkgPath:  e.Function.PkgPath,
			RecvType: e.Function.RecvType,
		}
		if e.Call == nil || e.Call.Pos == nil {
			fr.Position = token.Position{}
		} else {
			fr.Position = *e.Call.Pos
		}
		frames = append(frames, fr)
	}
	return frames
}
