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

// PrettyID returns the most human-readable GHSA identifier available.
func (s *SecurityAdvisory) PrettyID() string {
	for _, id := range s.Identifiers {
		if id.Type == "GHSA" {
			return id.Value
		}
	}
	return s.ID
}

// 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 {
	ID              string
	Identifiers     []Identifier
	Summary         string
	Description     string
	Origin          string
	Permalink       githubv4.URI
	PublishedAt     time.Time
	UpdatedAt       time.Time
	Vulnerabilities struct {
		Nodes []struct {
			Package struct {
				Name      string
				Ecosystem string
			}
			FirstPatchedVersion struct{ Identifier string }
			// TODO(https://go.dev/issue/52550): uncomment when
			// https://support.github.com/ticket/personal/0/1599280
			// is fixed.
			//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.ID, sa.PublishedAt, sa.UpdatedAt)
	}
	if sa.Vulnerabilities.PageInfo.HasNextPage {
		return nil, fmt.Errorf("%s has more than 100 vulns", sa.ID)
	}
	s := &SecurityAdvisory{
		ID:          sa.ID,
		Identifiers: sa.Identifiers,
		Summary:     sa.Summary,
		Description: sa.Description,
		Origin:      sa.Origin,
		Permalink:   sa.Permalink.URL.String(),
		PublishedAt: sa.PublishedAt,
		UpdatedAt:   sa.UpdatedAt,
	}
	for _, v := range sa.Vulnerabilities.Nodes {
		s.Vulns = append(s.Vulns, &Vuln{
			Package: v.Package.Name,
			// TODO(https://go.dev/issue/52550): uncomment when
			// https://support.github.com/ticket/personal/0/1599280
			// is fixed.
			//Severity:               v.Severity,
			EarliestFixedVersion:   v.FirstPatchedVersion.Identifier,
			VulnerableVersionRange: v.VulnerableVersionRange,
			UpdatedAt:              v.UpdatedAt,
		})
	}
	return s, nil
}

func newGitHubClient(ctx context.Context, accessToken string) *githubv4.Client {
	ts := oauth2.StaticTokenSource(&oauth2.Token{AccessToken: accessToken})
	tc := oauth2.NewClient(ctx, ts)
	return githubv4.NewClient(tc)
}

// List returns all SecurityAdvisories that affect Go,
// published or updated since the given time.
// If withCVE is true, selects only advisories that are
// connected to CVEs, otherwise selects only advisories without CVEs.
func List(ctx context.Context, accessToken string, since time.Time, withCVE bool) ([]*SecurityAdvisory, error) {
	client := newGitHubClient(ctx, accessToken)

	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 := client.Query(ctx, &query, vars); err != nil {
			return nil, err
		}
		for _, sa := range query.SAs.Nodes {
			if withCVE != isCVE(sa.Identifiers) {
				continue
			}
			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 ListForCVE(ctx context.Context, accessToken string, cve string) ([]*SecurityAdvisory, error) {
	client := newGitHubClient(ctx, accessToken)

	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 := 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
		}
		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 FetchGHSA(ctx context.Context, accessToken, ghsaID string) (_ *SecurityAdvisory, err error) {
	client := newGitHubClient(ctx, accessToken)

	var query struct {
		SA gqlSecurityAdvisory `graphql:"securityAdvisory(ghsaId: $id)"`
	}
	vars := map[string]any{
		"id": githubv4.String(ghsaID),
		"go": githubv4.SecurityAdvisoryEcosystemGo,
	}

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

	return query.SA.securityAdvisory()
}

func isCVE(ids []Identifier) bool {
	for _, id := range ids {
		if id.Type == "CVE" {
			return true
		}
	}
	return false
}
