package rust

import (
	"github.com/rust-secure-code/go-rustaudit"

	"github.com/anchore/packageurl-go"
	"github.com/anchore/syft/syft/file"
	"github.com/anchore/syft/syft/pkg"
)

// Pkg returns the standard `pkg.Package` representation of the package referenced within the Cargo.lock metadata.
func newPackageFromCargoMetadata(m pkg.RustCargoLockEntry, locations ...file.Location) pkg.Package {
	p := pkg.Package{
		Name:      m.Name,
		Version:   m.Version,
		Locations: file.NewLocationSet(locations...),
		PURL:      cargoLockPackageURL(m),
		Language:  pkg.Rust,
		Type:      pkg.RustPkg,
		Metadata:  m,
	}

	p.SetID()

	return p
}

func cargoLockPackageURL(m pkg.RustCargoLockEntry) string {
	// Cargo omits source for packages resolved from the local workspace or a
	// path dependency. A cargo PURL without a repository qualifier identifies
	// a package on crates.io, so emitting one for a local package can cause
	// downstream scanners to match unrelated registry vulnerabilities.
	if m.Source == "" {
		return ""
	}

	return packageURL(m.Name, m.Version)
}

func newPackageFromAudit(dep *rustaudit.Package, locations ...file.Location) pkg.Package {
	p := pkg.Package{
		Name:      dep.Name,
		Version:   dep.Version,
		PURL:      packageURL(dep.Name, dep.Version),
		Language:  pkg.Rust,
		Type:      pkg.RustPkg,
		Locations: file.NewLocationSet(locations...),
		Metadata: pkg.RustBinaryAuditEntry{
			Name:    dep.Name,
			Version: dep.Version,
			Source:  dep.Source,
		},
	}

	p.SetID()

	return p
}

// packageURL returns the PURL for the specific rust package (see https://github.com/package-url/purl-spec)
func packageURL(name, version string) string {
	return packageurl.NewPackageURL(
		packageurl.TypeCargo,
		"",
		name,
		version,
		nil,
		"",
	).ToString()
}
