// 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 issues provides a general way to interact with issues,
// and a client for interacting with the GitHub  issues API.
package issues

import (
	"context"
	"fmt"
	"net/url"
	"time"

	"github.com/google/go-github/v41/github"
	"golang.org/x/oauth2"
	"golang.org/x/vulndb/internal/derrors"
)

// Issue represents a GitHub issue.
type Issue struct {
	Number    int
	Title     string
	Body      string
	State     string
	Assignee  string
	Labels    []string
	CreatedAt time.Time
}

// IssuesOptions are options for Issues
type IssuesOptions struct {
	// State filters issues based on their state. Possible values are: open,
	// closed, all. Default is "open".
	State string

	// Labels filters issues based on their label.
	Labels []string
}

// Client is a shallow client for a github.Client.
type Client struct {
	GitHub *github.Client
	Owner  string
	Repo   string
}

// Config is used to initialize a new Client.
type Config struct {
	// Owner is the owner of a GitHub repo. For example, "golang" is the owner
	// for github.com/golang/vulndb.
	Owner string

	// Repo is the name of a GitHub repo. For example, "vulndb" is the repo
	// name for github.com/golang/vulndb.
	Repo string

	// Token is access token that authorizes and authenticates
	// requests to the GitHub API.
	Token string
}

// NewClient creates a Client that will create issues in
// the a GitHub repo.
func NewClient(ctx context.Context, cfg *Config) *Client {
	ts := oauth2.StaticTokenSource(&oauth2.Token{AccessToken: cfg.Token})
	tc := oauth2.NewClient(ctx, ts)
	c := github.NewClient(tc)
	return &Client{
		GitHub: c,
		Owner:  cfg.Owner,
		Repo:   cfg.Repo,
	}
}

// NewTestClient creates a Client for use in tests.
func NewTestClient(ctx context.Context, cfg *Config, baseURL *url.URL) *Client {
	c := NewClient(ctx, cfg)
	c.GitHub.BaseURL = baseURL
	c.GitHub.UploadURL = baseURL
	return c
}

// Destination returns the URL of the Github repo.
func (c *Client) Destination() string {
	return fmt.Sprintf("https://github.com/%s/%s", c.Owner, c.Repo)
}

// Reference returns the URL of the given issue.
func (c *Client) Reference(num int) string {
	return fmt.Sprintf("%s/issues/%d", c.Destination(), num)
}

// IssueExists reports whether an issue with the given ID exists.
func (c *Client) IssueExists(ctx context.Context, number int) (_ bool, err error) {
	defer derrors.Wrap(&err, "IssueExists(%d)", number)

	iss, _, err := c.GitHub.Issues.Get(ctx, c.Owner, c.Repo, number)
	if err != nil {
		return false, err
	}
	if iss != nil {
		fmt.Printf("ID = %d, Number = %d\n", iss.GetID(), iss.GetNumber())
		return true, nil
	}
	return false, nil
}

// convertGithubIssueToIssue converts a github.Issue to an Issue.
func convertGithubIssueToIssue(ghIss *github.Issue) *Issue {
	iss := &Issue{}
	if ghIss.Number != nil {
		iss.Number = *ghIss.Number
	}
	if ghIss.Title != nil {
		iss.Title = *ghIss.Title
	}
	if ghIss.Number != nil {
		iss.Number = *ghIss.Number
	}
	if ghIss.Body != nil {
		iss.Body = *ghIss.Body
	}
	if ghIss.CreatedAt != nil {
		iss.CreatedAt = *ghIss.CreatedAt
	}
	if ghIss.State != nil {
		iss.State = *ghIss.State
	}
	if ghIss.Assignee != nil {
		iss.Assignee = ghIss.Assignee.GetLogin()
	}
	if ghIss.Labels != nil {
		iss.Labels = make([]string, len(ghIss.Labels))
		for i, label := range ghIss.Labels {
			iss.Labels[i] = label.GetName()
		}
	}
	return iss
}

// Issue returns the issue with the given issue number.
func (c *Client) Issue(ctx context.Context, number int) (_ *Issue, err error) {
	defer derrors.Wrap(&err, "Issue(%d)", number)
	ghIss, _, err := c.GitHub.Issues.Get(ctx, c.Owner, c.Repo, number)
	if err != nil {
		return nil, err
	}
	iss := convertGithubIssueToIssue(ghIss)

	return iss, nil
}

// Issues returns all Github issues that match the filters in opts.
func (c *Client) Issues(ctx context.Context, opts IssuesOptions) (_ []*Issue, err error) {
	defer derrors.Wrap(&err, "Issues()")
	clientOpts := &github.IssueListByRepoOptions{
		State:  opts.State,
		Labels: opts.Labels,
		ListOptions: github.ListOptions{
			PerPage: 100,
		},
	}

	issues := []*Issue{}
	page := 1
	for {
		clientOpts.ListOptions.Page = page
		pageIssues, resp, err := c.GitHub.Issues.ListByRepo(ctx, c.Owner, c.Repo, clientOpts)
		if err != nil {
			return nil, err
		}
		for _, giss := range pageIssues {
			if giss.IsPullRequest() {
				continue
			}
			issues = append(issues, convertGithubIssueToIssue(giss))
		}
		if resp.NextPage == 0 {
			break
		}
		page = resp.NextPage
	}

	return issues, nil
}

// CreateIssue creates a new issue.
func (c *Client) CreateIssue(ctx context.Context, iss *Issue) (number int, err error) {
	defer derrors.Wrap(&err, "CreateIssue(%s)", iss.Title)

	req := &github.IssueRequest{
		Title: &iss.Title,
		Body:  &iss.Body,
	}
	if len(iss.Labels) > 0 {
		req.Labels = &iss.Labels
	}
	giss, _, err := c.GitHub.Issues.Create(ctx, c.Owner, c.Repo, req)
	if err != nil {
		return 0, err
	}
	return giss.GetNumber(), nil
}

// NewGoID creates a Go advisory ID based on the issue number
// and time of issue creation.
func (iss *Issue) NewGoID() string {
	var year int
	if !iss.CreatedAt.IsZero() {
		year = iss.CreatedAt.Year()
	}
	return fmt.Sprintf("GO-%04d-%04d", year, iss.Number)
}
