// Copyright 2023 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 osvutils provides utilities for working with Go OSV entries.
// It is separated from package osv because that package
// promises to only import from the standard library.
package osvutils

import (
	"errors"
	"fmt"
	"strings"

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

// Validate errors if there are any problems with the OSV Entry.
// It is used to validate OSV entries before publishing them to the
// Go vulnerability database, and has stricter requirements than
// the general OSV format.
func Validate(e *osv.Entry) (err error) {
	derrors.Wrap(&err, "Validate(%s)", e.ID)
	return validate(e, true)
}

// ValidateExceptTimestamps errors if there are any problems with the
// OSV Entry, with the exception of the timestamps (published, modified and
// withdrawn) which are not checked.
// This is used to validate entries at CL submit time, before their timestamps
// are corrected.
func ValidateExceptTimestamps(e *osv.Entry) (err error) {
	derrors.Wrap(&err, "ValidateExceptTimestamps(%s)", e.ID)
	return validate(e, false)
}

var (
	// Errors for incorrect timestamps.
	errNoModified             = errors.New("modified time must be non-zero")
	errNoPublished            = errors.New("published time must be non-zero")
	errPublishedAfterModified = errors.New("published time cannot be after modified time")

	// Errors for missing fields.
	errNoID                = errors.New("id field is empty")
	errNoSchemaVersion     = errors.New("schema_version field is empty")
	errNoSummary           = errors.New("summary field is empty")
	errNoDetails           = errors.New("details field is empty")
	errNoAffected          = errors.New("affected field is empty")
	errNoDatabaseSpecific  = errors.New("database_specific field is empty")
	errNoModule            = errors.New("affected field missing module path")
	errNotGoEcosystem      = errors.New("affected ecosystem is not Go")
	errNoRanges            = errors.New("affected field contains no ranges")
	errNoEcosystemSpecific = errors.New("affected field contains no ecosystem_specific field")
	errNoPackagePath       = errors.New("affected.ecosystem_specific.imports field has no package path")

	// Errors for invalid fields.
	errInvalidAlias           = errors.New("alias must be CVE or GHSA ID")
	errInvalidPkgsiteURL      = errors.New("database_specific.URL must be a link to https://pkg.go.dev/vuln/<Go id>")
	errInvalidPackagePath     = errors.New("package path must be prefixed by module path")
	errTooManyRanges          = errors.New("each module should have exactly one version range")
	errRangeTypeNotSemver     = errors.New("range type must be SEMVER")
	errNoRangeEvents          = errors.New("range must contain one or more events")
	errOutOfOrderRange        = errors.New("introduced and fixed versions must alternate")
	errUnsortedRange          = errors.New("range events must be in strictly ascending order")
	errNoIntroducedOrFixed    = errors.New("introduced or fixed must be set")
	errBothIntroducedAndFixed = errors.New("introduced and fixed cannot both be set in same event")
	errInvalidSemver          = errors.New("invalid or non-canonical semver version")
)

func validate(e *osv.Entry, checkTimestamps bool) (err error) {
	if checkTimestamps {
		switch {
		case e.Modified.IsZero():
			return errNoModified
		case e.Published.IsZero():
			return errNoPublished
		case e.Published.After(e.Modified.Time):
			return fmt.Errorf("%w (published=%s, modified=%s)", errPublishedAfterModified, e.Published, e.Modified)
		}
	}

	// Check for missing required fields.
	switch {
	case e.ID == "":
		return errNoID
	case e.SchemaVersion == "":
		return errNoSchemaVersion
	case e.Summary == "":
		return errNoSummary
	case e.Details == "" && !hasAdvisory(e):
		return errNoDetails
	case len(e.Affected) == 0:
		return errNoAffected
	case e.DatabaseSpecific == nil:
		return errNoDatabaseSpecific
	}

	for _, a := range e.Affected {
		if err := validateAffected(&a); err != nil {
			return err
		}
	}
	for _, alias := range e.Aliases {
		if !idstr.IsAliasType(alias) {
			return fmt.Errorf("%w (found alias %s)", errInvalidAlias, alias)
		}
	}

	return validateDatabaseSpecific(e.DatabaseSpecific)
}

func hasAdvisory(entry *osv.Entry) bool {
	for _, ref := range entry.References {
		if ref.Type == osv.ReferenceTypeAdvisory {
			return true
		}
	}
	return false
}

func validateAffected(a *osv.Affected) error {
	switch {
	case a.Module.Path == "":
		return errNoModule
	case a.Module.Ecosystem != osv.GoEcosystem:
		return errNotGoEcosystem
	}

	if err := ValidateRanges(a.Ranges); err != nil {
		return err
	}

	return validateEcosystemSpecific(a.EcosystemSpecific, a.Module.Path)
}

func ValidateRanges(ranges []osv.Range) error {
	switch {
	case len(ranges) == 0:
		return errNoRanges
	case len(ranges) > 1:
		return fmt.Errorf("%w (found %d ranges)", errTooManyRanges, len(ranges))
	}

	return validateRange(&ranges[0])
}

func validateRange(r *osv.Range) error {
	switch {
	case r.Type != osv.RangeTypeSemver:
		return fmt.Errorf("%w (found range type %q)",
			errRangeTypeNotSemver, r.Type)
	case len(r.Events) == 0:
		return errNoRangeEvents
	}

	// Check that all the events are valid and sorted in ascending order.
	prev, err := parseRangeEvent(&r.Events[0])
	if err != nil {
		return err
	}
	for _, event := range r.Events[1:] {
		current, err := parseRangeEvent(&event)
		if err != nil {
			return fmt.Errorf("invalid range event: %w", err)
		}
		// Introduced and fixed versions must alternate.
		if current.introduced == prev.introduced {
			return errOutOfOrderRange
		}
		if !less(prev.v, current.v) {
			return fmt.Errorf("%w (found %s>=%s)", errUnsortedRange, prev.v, current.v)
		}
		prev = current
	}

	return nil
}

func less(v, w string) bool {
	// Ensure that version 0 is always lowest.
	if v == "0" {
		return true
	}
	if w == "0" {
		return false
	}
	return version.Before(v, w)
}

type event struct {
	v          string
	introduced bool
}

func parseRangeEvent(e *osv.RangeEvent) (*event, error) {
	introduced, fixed := e.Introduced, e.Fixed

	var v string
	var isIntroduced bool
	switch {
	case introduced == "" && fixed == "":
		return nil, errNoIntroducedOrFixed
	case introduced != "" && fixed != "":
		return nil, errBothIntroducedAndFixed
	case introduced == "0":
		return &event{v: "0", introduced: true}, nil
	case introduced != "":
		v = introduced
		isIntroduced = true
	case fixed != "":
		v = fixed
		isIntroduced = false
	}

	if !version.IsValid(v) || v != version.Canonical(v) {
		return nil, fmt.Errorf("%w (found %s)", errInvalidSemver, v)
	}

	return &event{v: v, introduced: isIntroduced}, nil
}

func validateEcosystemSpecific(es *osv.EcosystemSpecific, module string) error {
	if es == nil {
		return errNoEcosystemSpecific
	}

	for _, pkg := range es.Packages {
		if pkg.Path == "" {
			return errNoPackagePath
		}
		// Package path must be prefixed by module path unless it is
		// in the Go standard library or toolchain.
		if (module != osv.GoStdModulePath && module != osv.GoCmdModulePath) &&
			!strings.HasPrefix(pkg.Path, module) {
			return fmt.Errorf("%w (found module=%q, package=%q)", errInvalidPackagePath, module, pkg.Path)
		}
	}

	return nil
}

func validateDatabaseSpecific(d *osv.DatabaseSpecific) error {
	if !idstr.IsGoAdvisory(d.URL) {
		return fmt.Errorf("%w (found URL %q)", errInvalidPkgsiteURL, d.URL)
	}
	return nil
}
