// Copyright 2021 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 vulncheck

import (
	"context"
	"fmt"
	"runtime"
	"sort"

	"golang.org/x/tools/go/packages"
	"golang.org/x/tools/go/packages/packagestest"
	"golang.org/x/vuln/client"
	"golang.org/x/vuln/internal/semver"
	"golang.org/x/vuln/osv"
)

type mockClient struct {
	client.Client
	ret map[string][]*osv.Entry
}

func (mc *mockClient) GetByModule(ctx context.Context, a string) ([]*osv.Entry, error) {
	return mc.ret[a], nil
}

// testClient contains the following test vulnerabilities
//
//	golang.org/amod/avuln.{VulnData.Vuln1, vulnData.Vuln2}
//	golang.org/bmod/bvuln.Vuln
//	archive/zip.OpenReader
var testClient = &mockClient{
	ret: map[string][]*osv.Entry{
		"golang.org/amod": []*osv.Entry{
			{
				ID: "VA",
				Affected: []osv.Affected{{
					Package: osv.Package{Name: "golang.org/amod"},
					Ranges:  osv.Affects{{Type: osv.TypeSemver, Events: []osv.RangeEvent{{Introduced: "1.0.0"}, {Fixed: "1.0.4"}, {Introduced: "1.1.2"}}}},
					EcosystemSpecific: osv.EcosystemSpecific{Imports: []osv.EcosystemSpecificImport{{
						Path:    "golang.org/amod/avuln",
						Symbols: []string{"VulnData.Vuln1", "VulnData.Vuln2"}},
					}},
				}},
			},
		},
		"golang.org/bmod": []*osv.Entry{
			{
				ID: "VB",
				Affected: []osv.Affected{{
					Package: osv.Package{Name: "golang.org/bmod"},
					Ranges:  osv.Affects{{Type: osv.TypeSemver}},
					EcosystemSpecific: osv.EcosystemSpecific{
						Imports: []osv.EcosystemSpecificImport{{
							Path:    "golang.org/bmod/bvuln",
							Symbols: []string{"Vuln"},
						}},
					},
				}},
			},
		},
		"stdlib": []*osv.Entry{
			{
				ID: "STD",
				Affected: []osv.Affected{{
					Package: osv.Package{Name: "stdlib"},
					// Range is populated also using runtime info for testing binaries since
					// setting fixed Go version for binaries is very difficult.
					Ranges: osv.Affects{{Type: osv.TypeSemver, Events: []osv.RangeEvent{{Introduced: "1.18"}, {Introduced: semver.GoTagToSemver(runtime.Version())}}}},
					EcosystemSpecific: osv.EcosystemSpecific{
						Imports: []osv.EcosystemSpecificImport{{
							Path:    "archive/zip",
							Symbols: []string{"OpenReader"},
						}},
					},
				}},
			},
		},
	},
}

func moduleVulnerabilitiesToString(mv moduleVulnerabilities) string {
	var s string
	for _, m := range mv {
		s += fmt.Sprintf("mod: %v\n", m.mod)
		for _, v := range m.vulns {
			s += fmt.Sprintf("\t%v\n", v)
		}
	}
	return s
}

func vulnsToString(vulns []*osv.Entry) string {
	var s string
	for _, v := range vulns {
		s += fmt.Sprintf("\t%v\n", v)
	}
	return s
}

func impGraphToStrMap(ig *ImportGraph) map[string][]string {
	m := make(map[string][]string)
	for _, n := range ig.Packages {
		for _, predId := range n.ImportedBy {
			pred := ig.Packages[predId]
			m[pred.Path] = append(m[pred.Path], n.Path)
		}
	}

	sortStrMap(m)
	return m
}

func reqGraphToStrMap(rg *RequireGraph) map[string][]string {
	m := make(map[string][]string)
	for _, n := range rg.Modules {
		for _, predId := range n.RequiredBy {
			pred := rg.Modules[predId]
			m[pred.Path] = append(m[pred.Path], n.Path)
		}
	}

	sortStrMap(m)
	return m
}

func callGraphToStrMap(cg *CallGraph) map[string][]string {
	type edge struct {
		// src and dest are ids ofr source and
		// destination nodes in a callgraph edge.
		src, dst int
	}
	// seen edges, to avoid repetitions
	seen := make(map[edge]bool)

	m := make(map[string][]string)
	for _, n := range cg.Functions {
		fName := n.String()
		for _, callsite := range n.CallSites {
			e := edge{src: callsite.Parent, dst: n.ID}
			if seen[e] {
				continue
			}
			caller := cg.Functions[e.src]
			callerName := caller.String()
			m[callerName] = append(m[callerName], fName)
		}
	}

	sortStrMap(m)
	return m
}

func pkgPathToImports(pkgs []*Package) map[string][]string {
	m := make(map[string][]string)
	seen := make(map[*Package]bool)
	var visit func(*Package)
	visit = func(p *Package) {
		if seen[p] {
			return
		}
		seen[p] = true
		var imports []string
		for _, i := range p.Imports {
			imports = append(imports, i.PkgPath)
			visit(i)
		}
		m[p.PkgPath] = imports
	}
	for _, p := range pkgs {
		visit(p)
	}
	sortStrMap(m)
	return m
}

func modulePathToVersion(pkgs []*Package) map[string]string {
	m := make(map[string]string)
	seen := make(map[*Package]bool)
	var visit func(*Package)
	visit = func(p *Package) {
		if seen[p] || p.Module == nil {
			return
		}
		seen[p] = true
		for _, i := range p.Imports {
			visit(i)
		}
		m[p.Module.Path] = p.Module.Version
	}
	for _, p := range pkgs {
		visit(p)
	}
	return m
}

// sortStrMap sorts the map string slice values to make them deterministic.
func sortStrMap(m map[string][]string) {
	for _, strs := range m {
		sort.Strings(strs)
	}
}

// loadPackages loads packages for patterns. Returns error if the loading failed
// or some of the specified packages have issues. In the latter case, the error
// message will contain information only for the first observed package with issues.
func loadPackages(e *packagestest.Exported, patterns ...string) ([]*packages.Package, error) {
	e.Config.Mode |= packages.NeedModule | packages.NeedName | packages.NeedFiles |
		packages.NeedCompiledGoFiles | packages.NeedImports | packages.NeedTypes |
		packages.NeedTypesSizes | packages.NeedSyntax | packages.NeedTypesInfo | packages.NeedDeps
	pkgs, err := packages.Load(e.Config, patterns...)
	if err != nil {
		return pkgs, err
	}

	for _, p := range pkgs {
		if len(p.Errors) > 0 {
			return pkgs, fmt.Errorf("%v", p.Errors)
		}
	}

	return pkgs, nil
}
