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

import (
	"encoding/json"
	"os"
	"path/filepath"
	"regexp"
	"sort"
	"strings"
	"time"

	"golang.org/x/exp/maps"
	"golang.org/x/vuln/osv"
	"golang.org/x/vulndb/internal/derrors"
	"golang.org/x/vulndb/internal/stdlib"
)

var (
	// stdFileName is the name of the .json file in the vulndb repo
	// that will contain info on standard library vulnerabilities.
	stdFileName = "stdlib"

	// toolchainFileName is the name of the .json file in the vulndb repo
	// that will contain info on toolchain (cmd/...) vulnerabilities.
	toolchainFileName = "toolchain"

	// osvDir is the name of the directory in the vulndb repo that
	// contains reports.
	OSVDir = "data/osv"

	// schemaVersion is used to indicate which version of the OSV schema a
	// particular vulnerability was exported with.
	schemaVersion = "1.3.1"
)

// GenerateOSVEntry create an osv.Entry for a  In addition to the report, it
// takes the ID for the vuln and a URL that will point to the entry in the vuln DB.
func (r *Report) GenerateOSVEntry(goID string, lastModified time.Time) osv.Entry {
	var credits []osv.Credit
	if r.Credit != "" {
		credits = append(credits, osv.Credit{
			Name: r.Credit,
		})
	}

	entry := osv.Entry{
		ID:            goID,
		Published:     r.Published,
		Modified:      lastModified,
		Withdrawn:     r.Withdrawn,
		Details:       trimWhitespace(r.Description),
		Credits:       credits,
		SchemaVersion: schemaVersion,
	}

	linkName := GetGoAdvisoryLink(goID)
	for _, m := range r.Modules {
		entry.Affected = append(entry.Affected, generateAffected(m, linkName))
	}
	for _, ref := range r.References {
		entry.References = append(entry.References, osv.Reference{
			Type: string(ref.Type),
			URL:  ref.URL,
		})
	}
	entry.Aliases = r.GetAliases()
	return entry
}

func GetOSVFilename(goID string) string {
	return filepath.Join(OSVDir, goID+".json")
}

// ReadOSV reads an osv.Entry from a file.
func ReadOSV(filename string) (entry osv.Entry, err error) {
	derrors.Wrap(&err, "ReadOSV(%s)", filename)
	if err = UnmarshalFromFile(filename, &entry); err != nil {
		return osv.Entry{}, err
	}
	return entry, nil
}

func UnmarshalFromFile(path string, v any) (err error) {
	content, err := os.ReadFile(path)
	if err != nil {
		return err
	}
	if err = json.Unmarshal(content, v); err != nil {
		return err
	}
	return nil
}

// ModulesForEntry returns the list of modules affected by an OSV entry.
func ModulesForEntry(entry osv.Entry) []string {
	mods := map[string]bool{}
	for _, a := range entry.Affected {
		mods[a.Package.Name] = true
	}
	return maps.Keys(mods)
}

func generateAffectedRanges(versions []VersionRange) osv.Affects {
	a := osv.AffectsRange{Type: osv.TypeSemver}
	if len(versions) == 0 || versions[0].Introduced == "" {
		a.Events = append(a.Events, osv.RangeEvent{Introduced: "0"})
	}
	for _, v := range versions {
		if v.Introduced != "" {
			a.Events = append(a.Events, osv.RangeEvent{Introduced: v.Introduced.Canonical()})
		}
		if v.Fixed != "" {
			a.Events = append(a.Events, osv.RangeEvent{Fixed: v.Fixed.Canonical()})
		}
	}
	return osv.Affects{a}
}

// trimWhitespace removes unnecessary whitespace from a string, but preserves
// paragraph breaks (indicated by two newlines).
func trimWhitespace(s string) string {
	s = strings.TrimSpace(s)
	// Replace single newlines with spaces.
	newlines := regexp.MustCompile(`([^\n])\n([^\n])`)
	s = newlines.ReplaceAllString(s, "$1 $2")
	// Replace instances of 2 or more newlines with exactly two newlines.
	paragraphs := regexp.MustCompile(`\s*\n\n\s*`)
	s = paragraphs.ReplaceAllString(s, "\n\n")
	// Replace tabs and double spaces with single spaces.
	spaces := regexp.MustCompile(`[ \t]+`)
	s = spaces.ReplaceAllString(s, " ")
	return s
}

func generateImports(m *Module) (imps []osv.EcosystemSpecificImport) {
	for _, p := range m.Packages {
		syms := append([]string{}, p.Symbols...)
		syms = append(syms, p.DerivedSymbols...)
		sort.Strings(syms)
		imps = append(imps, osv.EcosystemSpecificImport{
			Path:    p.Package,
			GOOS:    p.GOOS,
			GOARCH:  p.GOARCH,
			Symbols: syms,
		})
	}
	return imps
}

func generateAffected(m *Module, url string) osv.Affected {
	name := m.Module
	switch name {
	case stdlib.ModulePath:
		name = stdFileName
	case stdlib.ToolchainModulePath:
		name = toolchainFileName
	}
	return osv.Affected{
		Package: osv.Package{
			Name:      name,
			Ecosystem: osv.GoEcosystem,
		},
		Ranges:           generateAffectedRanges(m.Versions),
		DatabaseSpecific: osv.DatabaseSpecific{URL: url},
		EcosystemSpecific: osv.EcosystemSpecific{
			Imports: generateImports(m),
		},
	}
}
