// 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 ghsa supports GitHub security advisories.
package ghsa

import (
	"context"
	"fmt"
	"time"

	"github.com/shurcooL/githubv4"
	"golang.org/x/oauth2"
)

// A SecurityAdvisory represents a GitHub security advisory.
type SecurityAdvisory struct {
	// The GitHub Security Advisory identifier.
	ID string
	// A complete list of identifiers, e.g. CVE numbers.
	Identifiers []Identifier
	// A short description of the advisory.
	Summary string
	// A full description of the advisory.
	Description string
	// Where the advisory came from.
	Origin string
	// A link to a page for the advisory.
	Permalink string
	// When the advisory was first published.
	PublishedAt time.Time
	// References linked to by this advisory.
	References []Reference
	// When the advisory was last updated; should always be >= PublishedAt.
	UpdatedAt time.Time
	// The vulnerabilities associated with this advisory.
	Vulns []*Vuln
}

// An Identifier identifies an advisory according to some scheme or
// organization, given by the Type field. Example types are GHSA and CVE.
type Identifier struct {
	Type  string
	Value string
}

// A Reference is a URL linked to by the advisory.
type Reference struct {
	URL string
}

// A Vuln represents a vulnerability.
type Vuln struct {
	// The vulnerable Go package or module.
	Package string
	// The severity of the vulnerability.
	Severity githubv4.SecurityAdvisorySeverity
	// The earliest fixed version.
	EarliestFixedVersion string
	// A string representing the range of vulnerable versions.
	// E.g. ">= 1.0.3"
	VulnerableVersionRange string
	// When the vulnerability was last updated.
	UpdatedAt time.Time
}

// A gqlSecurityAdvisory represents a GitHub security advisory structured for
// GitHub's GraphQL schema. The fields must be exported to be populated by
// Github's Client.Query function.
type gqlSecurityAdvisory struct {
	GhsaID          string
	Identifiers     []Identifier
	Summary         string
	Description     string
	Origin          string
	Permalink       githubv4.URI
	References      []Reference
	PublishedAt     time.Time
	UpdatedAt       time.Time
	Vulnerabilities struct {
		Nodes []struct {
			Package struct {
				Name      string
				Ecosystem string
			}
			FirstPatchedVersion    struct{ Identifier string }
			Severity               githubv4.SecurityAdvisorySeverity
			UpdatedAt              time.Time
			VulnerableVersionRange string
		}
		PageInfo struct {
			HasNextPage bool
		}
	} `graphql:"vulnerabilities(first: 100, ecosystem: $go)"` // include only Go vulns
}

// securityAdvisory converts a gqlSecurityAdvisory into a SecurityAdvisory.
// Errors if the security advisory was updated before it was published, or if
// there are more than 100 vulnerabilities associated with the advisory.
func (sa *gqlSecurityAdvisory) securityAdvisory() (*SecurityAdvisory, error) {
	if sa.PublishedAt.After(sa.UpdatedAt) {
		return nil, fmt.Errorf("%s: published at %s, after updated at %s", sa.GhsaID, sa.PublishedAt, sa.UpdatedAt)
	}
	if sa.Vulnerabilities.PageInfo.HasNextPage {
		return nil, fmt.Errorf("%s has more than 100 vulns", sa.GhsaID)
	}
	var permalink string
	if sa.Permalink.URL != nil {
		permalink = sa.Permalink.URL.String()
	}
	s := &SecurityAdvisory{
		ID:          sa.GhsaID,
		Identifiers: sa.Identifiers,
		Summary:     sa.Summary,
		Description: sa.Description,
		Origin:      sa.Origin,
		Permalink:   permalink,
		References:  sa.References,
		PublishedAt: sa.PublishedAt,
		UpdatedAt:   sa.UpdatedAt,
	}
	for _, v := range sa.Vulnerabilities.Nodes {
		s.Vulns = append(s.Vulns, &Vuln{
			Package:                v.Package.Name,
			Severity:               v.Severity,
			EarliestFixedVersion:   v.FirstPatchedVersion.Identifier,
			VulnerableVersionRange: v.VulnerableVersionRange,
			UpdatedAt:              v.UpdatedAt,
		})
	}
	return s, nil
}

// Client is a client that can fetch data about GitHub security advisories.
type Client struct {
	client *githubv4.Client
	token  string
}

// NewClient creates a new client for making requests to the GHSA API.
func NewClient(ctx context.Context, accessToken string) *Client {
	ts := oauth2.StaticTokenSource(&oauth2.Token{AccessToken: accessToken})
	tc := oauth2.NewClient(ctx, ts)
	return &Client{
		client: githubv4.NewClient(tc),
		token:  accessToken,
	}
}

// List returns all SecurityAdvisories that affect Go,
// published or updated since the given time.
func (c *Client) List(ctx context.Context, since time.Time) ([]*SecurityAdvisory, error) {
	var query struct { // the GraphQL query
		SAs struct {
			Nodes    []gqlSecurityAdvisory
			PageInfo struct {
				EndCursor   githubv4.String
				HasNextPage bool
			}
		} `graphql:"securityAdvisories(updatedSince: $since, first: 100, after: $cursor)"`
	}
	vars := map[string]any{
		"cursor": (*githubv4.String)(nil),
		"go":     githubv4.SecurityAdvisoryEcosystemGo,
		"since":  githubv4.DateTime{Time: since},
	}

	var sas []*SecurityAdvisory
	// We need a loop to page through the list. The GitHub API limits us to 100
	// values per call.
	for {
		if err := c.client.Query(ctx, &query, vars); err != nil {
			return nil, err
		}
		for _, sa := range query.SAs.Nodes {
			if len(sa.Vulnerabilities.Nodes) == 0 {
				continue
			}
			s, err := sa.securityAdvisory()
			if err != nil {
				return nil, err
			}
			sas = append(sas, s)
		}
		if !query.SAs.PageInfo.HasNextPage {
			break
		}
		vars["cursor"] = githubv4.NewString(query.SAs.PageInfo.EndCursor)
	}
	return sas, nil
}

func (c *Client) ListForCVE(ctx context.Context, cve string) ([]*SecurityAdvisory, error) {
	var query struct { // The GraphQL query
		SAs struct {
			Nodes    []gqlSecurityAdvisory
			PageInfo struct {
				EndCursor   githubv4.String
				HasNextPage bool
			}
		} `graphql:"securityAdvisories(identifier: $id, first: 100)"`
	}
	vars := map[string]any{
		"id": githubv4.SecurityAdvisoryIdentifierFilter{
			Type:  githubv4.SecurityAdvisoryIdentifierTypeCve,
			Value: githubv4.String(cve),
		},
		"go": githubv4.SecurityAdvisoryEcosystemGo,
	}

	if err := c.client.Query(ctx, &query, vars); err != nil {
		return nil, err
	}
	if query.SAs.PageInfo.HasNextPage {
		return nil, fmt.Errorf("CVE %s has more than 100 GHSAs", cve)
	}
	var sas []*SecurityAdvisory
	for _, sa := range query.SAs.Nodes {
		if len(sa.Vulnerabilities.Nodes) == 0 {
			continue
		}
		exactMatch := false
		for _, id := range sa.Identifiers {
			if id.Type == "CVE" && id.Value == cve {
				exactMatch = true
				continue
			}
		}
		if !exactMatch {
			continue
		}

		s, err := sa.securityAdvisory()
		if err != nil {
			return nil, err
		}
		sas = append(sas, s)
	}
	return sas, nil
}

// FetchGHSA returns the SecurityAdvisory for the given Github Security
// Advisory ID.
func (c *Client) FetchGHSA(ctx context.Context, ghsaID string) (_ *SecurityAdvisory, err error) {
	var query struct {
		SA gqlSecurityAdvisory `graphql:"securityAdvisory(ghsaId: $id)"`
	}
	vars := map[string]any{
		"id": githubv4.String(ghsaID),
		"go": githubv4.SecurityAdvisoryEcosystemGo,
	}

	if err := c.client.Query(ctx, &query, vars); err != nil {
		return nil, err
	}
	return query.SA.securityAdvisory()
}
