// 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 ghsarepo provides a client and utilities for reading
// GitHub security advisories directly from the Git repo
// https://github.com/github/advisory-database.
//
// This allows us to read GHSAs in OSV format instead of
// the SecurityAdvisory format output by the GraphQL API.
package ghsarepo

import (
	"context"
	"encoding/json"

	"github.com/go-git/go-git/v5"
	"github.com/go-git/go-git/v5/storage/memory"
	"golang.org/x/exp/maps"
	"golang.org/x/vulndb/internal/genericosv"
	"golang.org/x/vulndb/internal/gitrepo"
)

type Client struct {
	byID    map[string]*genericosv.Entry
	byAlias map[string][]*genericosv.Entry
}

const URL = "https://github.com/github/advisory-database"
const DirectURLPrefix = "https://raw.githubusercontent.com/github/advisory-database/main/advisories/github-reviewed"

// NewDefaultClient returns a client to read from the GHSA database.
// It clones the Git repo at https://github.com/github/advisory-database,
// which can take around ~20 seconds.
func NewDefaultClient() (*Client, error) {
	repo, err := git.Clone(memory.NewStorage(), nil, &git.CloneOptions{
		URL:           URL,
		ReferenceName: "refs/heads/main",
		SingleBranch:  true,
		Depth:         1,
		Tags:          git.NoTags,
		NoCheckout:    true,
	})
	if err != nil {
		return nil, err
	}
	return NewClient(repo)
}

func NewLocalClient(ctx context.Context, path string) (*Client, error) {
	repo, err := gitrepo.Open(ctx, path)
	if err != nil {
		return nil, err
	}
	return NewClient(repo)
}

// NewClient returns a client that reads from the GHSA database
// in the given repo, which must follow the structure of
// https://github.com/github/advisory-database.
func NewClient(repo *git.Repository) (*Client, error) {
	hc, err := gitrepo.HeadCommit(repo)
	if err != nil {
		return nil, err
	}
	files, err := Files(repo, hc)
	if err != nil {
		return nil, err
	}

	c := &Client{
		byID:    make(map[string]*genericosv.Entry),
		byAlias: make(map[string][]*genericosv.Entry),
	}

	for _, f := range files {
		var advisory genericosv.Entry
		b, err := f.ReadAll(repo)
		if err != nil {
			return nil, err
		}
		if err := json.Unmarshal(b, &advisory); err != nil {
			return nil, err
		}
		if !advisory.AffectsGo() {
			continue
		}
		if advisory.IsWithdrawn() {
			continue
		}
		c.byID[advisory.ID] = &advisory
		for _, alias := range advisory.Aliases {
			c.byAlias[alias] = append(c.byAlias[alias], &advisory)
		}
	}

	return c, nil
}

// IDs returns all the GHSA IDs in the GHSA database
// that affect Go and are not withdrawn.
func (c *Client) IDs() []string {
	return maps.Keys(c.byID)
}

// List returns all the genericosv.Entry entries in the GHSA database
// that affect Go and are not withdrawn.
func (c *Client) List() []*genericosv.Entry {
	return maps.Values(c.byID)
}

// ByGHSA returns the genericosv.Entry entry for the given GHSA, or nil if none
// exists.
func (c *Client) ByGHSA(ghsa string) *genericosv.Entry {
	return c.byID[ghsa]
}

// ByCVE returns the genericosv.Entry entries for the given CVE, or nil if none
// exist.
func (c *Client) ByCVE(cve string) []*genericosv.Entry {
	return c.byAlias[cve]
}
