// Copyright 2020 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 secret provides a client interface for interacting
// with the GCP Secret Management service.
package secret

import (
	"context"
	"fmt"
	"io"
	"log"
	"path"

	"cloud.google.com/go/compute/metadata"
	secretmanager "cloud.google.com/go/secretmanager/apiv1"
	"cloud.google.com/go/secretmanager/apiv1/secretmanagerpb"
	gax "github.com/googleapis/gax-go/v2"
)

const (
	// NameBuilderMasterKey is the secret name for the builder master key.
	NameBuilderMasterKey = "builder-master-key"

	// NameFarmerRunBench is the secret name for farmer run bench.
	NameFarmerRunBench = "farmer-run-bench"

	// NameGerritbotGitCookies is the secret name for Gerritbot Git cookies.
	NameGerritbotGitCookies = "gerritbot-gitcookies"

	// NameGitHubSSH is the secret name for GitHub SSH key.
	NameGitHubSSH = "github-ssh"

	// NameGitHubSSHKey is the secret name for the GitHub SSH private key.
	NameGitHubSSHKey = "github-ssh-private-key"

	// NameGobotPassword is the secret name for the gobot@golang.org Gerrit account password.
	NameGobotPassword = "gobot-password"

	// NameGomoteSSHCAPrivateKey is the secret name for the gomote SSH certificate authority private key.
	NameGomoteSSHCAPrivateKey = "gomote-ssh-ca-private-key"

	// NameGomoteSSHCAPublicKey is the secret name for the gomote SSH certificate authority public key.
	NameGomoteSSHCAPublicKey = "gomote-ssh-ca-public-key"

	// NameGomoteSSHPrivateKey is the secret name for the gomote SSH private key.
	NameGomoteSSHPrivateKey = "gomote-ssh-private-key"

	// NameGomoteSSHPublicKey is the secret name for the gomote SSH public key.
	NameGomoteSSHPublicKey = "gomote-ssh-public-key"

	// NameMaintnerGitHubToken is the secret name for the Maintner GitHub token.
	NameMaintnerGitHubToken = "maintner-github-token"

	// NameWatchflakesGitHubToken is the secret name for the watchflakes GitHub token.
	NameWatchflakesGitHubToken = "watchflakes-github-token"

	// NameGitHubWebhookSecret is the secret name for a golang/go GitHub webhook secret.
	NameGitHubWebhookSecret = "github-webhook-secret"

	// NamePubSubHelperWebhook is the secret name for the pubsub helper webhook secret.
	NamePubSubHelperWebhook = "pubsubhelper-webhook-secret"

	// NameAWSAccessKey is the secret name for the AWS access key.
	NameAWSAccessKey = "aws-access-key"

	// NameAWSKeyID is the secret name for the AWS key id.
	NameAWSKeyID = "aws-key-id"

	// NameSendGridAPIKey is the secret name for a Go project SendGrid API key.
	// This API key only allows sending email.
	NameSendGridAPIKey = "sendgrid-sendonly-api-key"

	// NameTwitterAPISecret is the secret name for Twitter API credentials for
	// posting tweets from the Go project's Twitter account (twitter.com/golang).
	//
	// The secret value encodes relevant keys and their secrets as
	// a JSON object that can be unmarshaled into TwitterCredentials:
	//
	// 	{
	// 		"ConsumerKey":       "...",
	// 		"ConsumerSecret":    "...",
	// 		"AccessTokenKey":    "...",
	// 		"AccessTokenSecret": "..."
	// 	}
	NameTwitterAPISecret = "twitter-api-secret"
	// NameStagingTwitterAPISecret is the secret name for Twitter API credentials
	// for posting tweets using a staging test Twitter account.
	//
	// This secret is available in the Secret Manager of the x/build staging GCP project.
	//
	// The secret value encodes relevant keys and their secrets as
	// a JSON object that can be unmarshaled into TwitterCredentials.
	NameStagingTwitterAPISecret = "staging-" + NameTwitterAPISecret

	// NameMastodonAPISecret is the secret name for Mastodon API credentials
	// for posting to Hachyderm.io/@golang.  The secret value is a JSON
	// encoding of the MastodonCredentials.
	NameMastodonAPISecret = "mastodon-api-secret"

	// NameMacServiceAPIKey is the secret name for the MacService API key.
	NameMacServiceAPIKey = "macservice-api-key"
)

// TwitterCredentials holds Twitter API credentials.
type TwitterCredentials struct {
	ConsumerKey       string
	ConsumerSecret    string
	AccessTokenKey    string
	AccessTokenSecret string
}

type MastodonCredentials struct {
	// Log in to <Instance> as your bot account,
	// navigate to Profile -> Development,
	// Click on <Application> in the Application column,
	// and it will reveal Client Key, Client Secret, and Access Token
	Instance      string // Instance (e.g. "botsin.space")
	Application   string // Application name (e.g. ""Go benchmarking bot"")
	ClientKey     string // Client Key
	ClientSecret  string // Client secret
	AccessToken   string // Access token
	TestRecipient string // For testing only, ignored by non-test API
}

func (t TwitterCredentials) String() string {
	return fmt.Sprintf("{%s (redacted) %s (redacted)}", t.ConsumerKey, t.AccessTokenKey)
}
func (t TwitterCredentials) GoString() string {
	return fmt.Sprintf("secret.TwitterCredentials{ConsumerKey:%q ConsumerSecret:(redacted) AccessTokenKey:%q AccessTokenSecret:(redacted)}", t.ConsumerKey, t.AccessTokenKey)
}

func (t MastodonCredentials) String() string {
	return fmt.Sprintf("{%s %s (redacted) (redacted) (redacted)}", t.Instance, t.Application)
}
func (t MastodonCredentials) GoString() string {
	return fmt.Sprintf("secret.MastodonCredentials{Instance:%q Application:%q ClientKey:(redacted) ClientSecret:(redacted) AccessToken:(redacted)}", t.Instance, t.Application)
}

type secretClient interface {
	AccessSecretVersion(ctx context.Context, req *secretmanagerpb.AccessSecretVersionRequest, opts ...gax.CallOption) (*secretmanagerpb.AccessSecretVersionResponse, error)
	io.Closer
}

// Client is used to interact with the GCP Secret Management service.
type Client struct {
	client    secretClient
	projectID string // projectID specifies the ID of the GCP project where secrets are retrieved from.
}

// NewClient creates a Secret Manager Client
// that targets the current GCP instance's project ID.
func NewClient() (*Client, error) {
	projectID, err := metadata.ProjectID()
	if err != nil {
		return nil, err
	}

	// The default client configuration includes retries on transient failures.
	// It is a non-blocking blocking call which is why we do not set a timeout on
	// the context.
	client, err := secretmanager.NewClient(context.Background())
	if err != nil {
		return nil, err
	}

	return &Client{
		client:    client,
		projectID: projectID,
	}, nil
}

// NewClientInProject creates a Secret Manager Client
// that targets the specified GCP project ID.
func NewClientInProject(projectID string) (*Client, error) {
	client, err := secretmanager.NewClient(context.Background())
	if err != nil {
		return nil, err
	}
	return &Client{
		client:    client,
		projectID: projectID,
	}, nil
}

// Retrieve the named secret from the Secret Management service.
func (smc *Client) Retrieve(ctx context.Context, name string) (string, error) {
	r, err := smc.client.AccessSecretVersion(ctx, &secretmanagerpb.AccessSecretVersionRequest{
		Name: buildNamePath(smc.projectID, name, "latest"),
	})
	if err != nil {
		return "", err
	}
	return string(r.Payload.GetData()), nil
}

// Close closes the connection to the Secret Management service.
func (smc *Client) Close() error {
	return smc.client.Close()
}

// buildNamePath creates the name path required by the Secret Management service to
// query for a secret.
func buildNamePath(projectID, name, version string) string {
	return path.Join("projects", projectID, "secrets", name, "versions", version)
}

// MustNewClient instantiates an instance of the Secret Manager Client. If there is an error
// this function will exit.
func MustNewClient() *Client {
	c, err := NewClient()
	if err != nil {
		log.Fatalf("unable to create secret client %v", err)
	}
	return c
}
