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

import (
	"errors"
	"fmt"
	"regexp"
	"slices"
	"strings"

	"golang.org/x/vulndb/internal/derrors"
	"golang.org/x/vulndb/internal/idstr"
	"golang.org/x/vulndb/internal/osv"
	"golang.org/x/vulndb/internal/proxy"
	"golang.org/x/vulndb/internal/report"
	"golang.org/x/vulndb/internal/stdlib"
	"golang.org/x/vulndb/internal/version"
)

var (
	// The universal unique identifier for the Go Project CNA, which
	// needs to be included CVE JSON 5.0 records.
	GoOrgUUID = "1bb62c36-49e3-4200-9d77-64a1400537cc"
)

// FromReport creates a CVE in 5.0 format from a YAML report file.
func FromReport(r *report.Report) (_ *CVERecord, err error) {
	defer derrors.Wrap(&err, "FromReport(%q)", r.ID)

	if r.CVEMetadata == nil {
		return nil, errors.New("report missing cve_metadata section")
	}
	if r.CVEMetadata.ID == "" {
		return nil, errors.New("report missing CVE ID")
	}
	description := r.CVEMetadata.Description
	if description == "" {
		description = r.Description.String()
	}
	if r.CVEMetadata.CWE == "" {
		return nil, errors.New("report missing CWE")
	}

	c := &CNAPublishedContainer{
		ProviderMetadata: ProviderMetadata{
			OrgID: GoOrgUUID,
		},
		Title: report.RemoveNewlines(r.Summary.String()),
		Descriptions: []Description{
			{
				Lang:  "en",
				Value: report.RemoveNewlines(description),
			},
		},
		ProblemTypes: []ProblemType{
			{
				Descriptions: []ProblemTypeDescription{
					{
						Lang:        "en",
						Description: r.CVEMetadata.CWE,
					},
				},
			},
		},
	}

	for _, m := range r.Modules {
		versions, defaultStatus := versionsToVersionRanges(m.Versions)
		for _, p := range m.Packages {
			affected := Affected{
				Vendor:        report.Vendor(m.Module),
				Product:       p.Package,
				CollectionURL: "https://pkg.go.dev",
				PackageName:   p.Package,
				Versions:      versions,
				DefaultStatus: defaultStatus,
				Platforms:     p.GOOS,
			}
			for _, symbol := range p.AllSymbols() {
				affected.ProgramRoutines = append(affected.ProgramRoutines, ProgramRoutine{Name: symbol})
			}
			c.Affected = append(c.Affected, affected)
		}
	}

	for _, ref := range r.References {
		c.References = append(c.References, Reference{URL: ref.URL})
	}
	c.References = append(c.References, Reference{
		URL: idstr.GoAdvisory(r.ID),
	})
	for _, ref := range r.CVEMetadata.References {
		c.References = append(c.References, Reference{URL: ref})
	}

	for _, credit := range r.Credits {
		c.Credits = append(c.Credits, Credit{
			Lang:  "en",
			Value: credit,
		})
	}

	return &CVERecord{
		DataType:    "CVE_RECORD",
		DataVersion: "5.0",
		Metadata: Metadata{
			ID: r.CVEMetadata.ID,
		},
		Containers: Containers{
			CNAContainer: *c,
		},
	}, nil
}

const (
	typeSemver  = "semver"
	versionZero = "0"
)

func versionsToVersionRanges(vs report.Versions) ([]VersionRange, VersionStatus) {
	if len(vs) == 0 {
		// If there are no recorded versions affected, we assume all versions are affected.
		return nil, StatusAffected
	}

	var vrs []VersionRange

	// If there is no final fixed version, then the default status is
	// "affected" and we express the versions in terms of which ranges
	// are *unaffected*. This is due to the fact that the CVE schema
	// does not allow us to express a range as "version X.X.X and above are affected".
	if vs[len(vs)-1].Type != report.VersionTypeFixed {
		current := &VersionRange{}
		for _, vr := range vs {
			if vr.IsIntroduced() {
				if current.Introduced == "" {
					current.Introduced = versionZero
				}
				current.Fixed = Version(vr.Version)
				current.Status = StatusUnaffected
				current.VersionType = typeSemver
				vrs = append(vrs, *current)
				current = &VersionRange{}
			} else if vr.IsFixed() {
				current.Introduced = Version(vr.Version)
			}
		}
		return vrs, StatusAffected
	}

	// Otherwise, express the version ranges normally as affected ranges,
	// with a default status of "unaffected".
	var current *VersionRange
	for _, vr := range vs {
		if vr.IsIntroduced() {
			if current == nil {
				current = &VersionRange{
					Status:      StatusAffected,
					VersionType: typeSemver,
					Introduced:  Version(vr.Version),
				}
			}
		}
		if vr.IsFixed() {
			if current == nil {
				current = &VersionRange{
					Status:      StatusAffected,
					VersionType: typeSemver,
					Introduced:  versionZero,
				}
			}
			current.Fixed = Version(vr.Version)
			vrs = append(vrs, *current)
			current = nil
		}
	}

	return vrs, StatusUnaffected
}

var _ report.Source = &CVERecord{}

func (c *CVERecord) ToReport(pxc *proxy.Client, modulePath string) *report.Report {
	return cve5ToReport(c, pxc, modulePath)
}

func (c *CVERecord) SourceID() string {
	return c.Metadata.ID
}

func (c *CVERecord) ReferenceURLs() []string {
	var result []string
	for _, r := range c.Containers.CNAContainer.References {
		result = append(result, r.URL)
	}
	return result
}

func cve5ToReport(c *CVERecord, pxc *proxy.Client, modulePath string) *report.Report {
	cna := c.Containers.CNAContainer

	var description report.Description
	for _, d := range cna.Descriptions {
		if d.Lang == "en" {
			description += report.Description(d.Value + "\n")
		}
	}

	var credits []string
	for _, c := range cna.Credits {
		credits = append(credits, c.Value)
	}

	var refs []*report.Reference
	for _, ref := range c.Containers.CNAContainer.References {
		refs = append(refs, convertRef(ref))
	}

	r := &report.Report{
		Modules:     affectedToModules(cna.Affected, pxc, modulePath),
		Summary:     report.Summary(cna.Title),
		Description: description,
		Credits:     credits,
		References:  refs,
	}

	r.AddCVE(c.Metadata.ID, getCWE5(&cna), isGoCNA5(&cna))
	return r
}

func convertRef(ref Reference) *report.Reference {
	if t := typeFromTags(ref.Tags); t != osv.ReferenceTypeWeb {
		return &report.Reference{
			Type: t,
			URL:  ref.URL,
		}
	}
	return report.ReferenceFromUrl(ref.URL)
}

const (
	refTagIssue          = "issue-tracking"
	refTagMailingList    = "mailing-list"
	refTagPatch          = "patch"
	refTagReleaseNotes   = "release-notes"
	refTag3PAdvisory     = "third-party-advisory"
	refTagVendorAdvisory = "vendor-advisory"
	refTagVdbEntry       = "vdb-entry"
	refTagMedia          = "media-coverage"
	refTagTechnical      = "technical-description"
	refTagRelated        = "related"
	refTagGovt           = "government resource"
	refTagMitigation     = "mitigation"
	// uncategorized:
	// "broken-link"
	// "customer-entitlement"
	// "not-applicable"
	// "permissions-required"
	// "product"
	// "signature"
)

func tagToType(tag string) osv.ReferenceType {
	switch tag {
	case refTagVendorAdvisory:
		return osv.ReferenceTypeAdvisory
	case refTagIssue:
		return osv.ReferenceTypeReport
	case refTagPatch:
		return osv.ReferenceTypeFix
	}
	return defaultType
}

var order = []osv.ReferenceType{
	osv.ReferenceTypeAdvisory,
	osv.ReferenceTypeFix,
	osv.ReferenceTypeReport,
	osv.ReferenceTypeWeb,
}

var defaultType = osv.ReferenceTypeWeb

func bestType(types []osv.ReferenceType) osv.ReferenceType {
	if len(types) == 0 {
		return defaultType
	} else if len(types) == 1 {
		return types[0]
	}

	slices.SortStableFunc(types, func(a, b osv.ReferenceType) int {
		if a == b {
			return 0
		}
		for _, t := range order {
			if a == t {
				return -1
			}
			if b == t {
				return 1
			}
		}
		return 0
	})

	return types[0]
}

func typeFromTags(tags []string) osv.ReferenceType {
	var types []osv.ReferenceType
	for _, tag := range tags {
		if t := tagToType(tag); t != "" {
			types = append(types, t)
		}
	}
	return bestType(types)

}

func getCWE5(c *CNAPublishedContainer) string {
	if len(c.ProblemTypes) == 0 || len(c.ProblemTypes[0].Descriptions) == 0 {
		return ""
	}
	return c.ProblemTypes[0].Descriptions[0].Description
}

func isGoCNA5(c *CNAPublishedContainer) bool {
	return c.ProviderMetadata.OrgID == GoOrgUUID
}

func affectedToModules(as []Affected, pxc *proxy.Client, fallbackModule string) []*report.Module {
	// Use a placeholder module if there is no information on
	// modules/packages in the CVE.
	if len(as) == 0 {
		return []*report.Module{{
			Module: fallbackModule,
		}}
	}

	var modules []*report.Module
	for _, a := range as {
		modules = append(modules, affectedToModule(&a, pxc, fallbackModule))
	}

	return modules
}

func affectedToModule(a *Affected, pxc *proxy.Client, fallbackModule string) *report.Module {
	var pkgPath string
	isSet := func(s string) bool {
		const na = "n/a"
		return s != "" && s != na
	}
	switch {
	case isSet(a.PackageName):
		pkgPath = a.PackageName
	case isSet(a.Product):
		pkgPath = a.Product
	case isSet(a.Vendor):
		pkgPath = a.Vendor
	default:
		pkgPath = fallbackModule
	}

	modulePath := fallbackModule
	if stdlib.Contains(modulePath) && stdlib.Contains(pkgPath) {
		// Standard library and toolchain
		if strings.HasPrefix(pkgPath, stdlib.ToolchainModulePath) {
			modulePath = stdlib.ToolchainModulePath
		} else {
			modulePath = stdlib.ModulePath
		}
	} else if mp, err := pxc.FindModule(pkgPath); mp != "" && err == nil { // no error
		// Recognized third-party package path
		modulePath = mp
	} else {
		// Unrecognized third-party package path
		pkgPath = fallbackModule
	}

	vs, uvs := convertVersions(a.Versions, a.DefaultStatus)

	// Add a package if we have any meaningful package-level data.
	var pkgs []*report.Package
	if pkgPath != modulePath || len(a.ProgramRoutines) != 0 || len(a.Platforms) != 0 {
		var symbols []string
		for _, s := range a.ProgramRoutines {
			symbols = append(symbols, s.Name)
		}
		pkgs = []*report.Package{
			{
				Package: pkgPath,
				Symbols: symbols,
				GOOS:    a.Platforms,
			},
		}
	}

	return &report.Module{
		Module:              modulePath,
		Versions:            vs,
		UnsupportedVersions: uvs,
		Packages:            pkgs,
	}
}

func convertVersions(vrs []VersionRange, defaultStatus VersionStatus) (vs report.Versions, uvs report.Versions) {
	for _, vr := range vrs {
		// Version ranges starting with "n/a" don't have any meaningful data.
		if vr.Introduced == "n/a" {
			continue
		}
		v, ok := toVersions(&vr, defaultStatus)
		if ok {
			vs = append(vs, v...)
			continue
		}
		uvs = append(uvs, toUnsupported(&vr, defaultStatus))
	}
	return vs, uvs
}

var (
	// Regex for matching version strings like "<= X, < Y".
	introducedFixedRE = regexp.MustCompile(`^>= (.+), < (.+)$`)
	// Regex for matching version strings like "< Y".
	fixedRE = regexp.MustCompile(`^< (.+)$`)
)

func toVersions(cvr *VersionRange, defaultStatus VersionStatus) (report.Versions, bool) {
	if cvr == nil {
		return nil, true
	}

	intro, fixed := version.TrimPrefix(string(cvr.Introduced)), version.TrimPrefix(string(cvr.Fixed))

	if intro == "" && fixed == "" {
		return nil, true
	}

	// Handle special cases where the info is not quite correctly encoded but
	// we can still figure out the intent.

	// Case one: introduced version is of the form "<= X, < Y".
	if m := introducedFixedRE.FindStringSubmatch(intro); len(m) == 3 {
		return report.Versions{
			report.Introduced(m[1]),
			report.Fixed(m[2]),
		}, true
	}

	// Case two: introduced version is of the form "< Y".
	if m := fixedRE.FindStringSubmatch(intro); len(m) == 2 {
		return report.Versions{
			report.Fixed(m[1]),
		}, true
	}

	// For now, don't attempt to fix any other cases we don't understand.
	if cvr.VersionType != typeSemver ||
		cvr.LessThanOrEqual != "" ||
		cvr.Status != StatusAffected ||
		defaultStatus == StatusAffected {
		return nil, false
	}

	if intro == "0" {
		return report.Versions{
			report.Fixed(fixed),
		}, true
	}

	return report.Versions{
		report.Introduced(intro), report.Fixed(fixed),
	}, true
}

func toUnsupported(cvr *VersionRange, defaultStatus VersionStatus) *report.Version {
	var version string
	switch {
	case cvr.Fixed != "":
		version = fmt.Sprintf("%s from %s before %s", cvr.Status, cvr.Introduced, cvr.Fixed)
	case cvr.LessThanOrEqual != "":
		version = fmt.Sprintf("%s from %s to %s", cvr.Status, cvr.Introduced, cvr.LessThanOrEqual)
	default:
		version = fmt.Sprintf("%s at %s", cvr.Status, cvr.Introduced)
	}
	if defaultStatus != "" {
		version = fmt.Sprintf("%s (default: %s)", version, defaultStatus)
	}
	return &report.Version{
		Version: version,
		Type:    "cve_version_range",
	}
}
