// Package buildbucket provides tools for interacting with the buildbucket API.
package buildbucket

import (
	"context"
	"net/http"

	buildbucketpb "go.chromium.org/luci/buildbucket/proto"
	structpb "google.golang.org/protobuf/types/known/structpb"

	"go.chromium.org/luci/grpc/prpc"
	"go.skia.org/infra/go/buildbucket/common"
	"go.skia.org/infra/go/skerr"
)

const (
	BUILD_URL_TMPL = "https://%s/build/%d"
	DEFAULT_HOST   = "cr-buildbucket.appspot.com"
)

var (
	DEFAULT_SCOPES = []string{
		"https://www.googleapis.com/auth/userinfo.email",
		"https://www.googleapis.com/auth/userinfo.profile",
	}
)

type BuildBucketInterface interface {
	// GetBuild retrieves the build with the given ID.
	GetBuild(ctx context.Context, buildId int64) (*buildbucketpb.Build, error)
	// Search retrieves Builds which match the given criteria.
	Search(ctx context.Context, pred *buildbucketpb.BuildPredicate) ([]*buildbucketpb.Build, error)
	// GetTrybotsForCL retrieves trybot results for the given CL using the
	// optional tags.
	GetTrybotsForCL(ctx context.Context, issue, patchset int64, gerritUrl string, tags map[string]string) ([]*buildbucketpb.Build, error)
	// ScheduleBuilds schedules the specified builds on the given CL. Builds are
	// scheduled with one batch request to buildbucket.
	// builds is the slice of which builds should be scheduled by buildbucket.
	// Eg: ["Infra-PerCommit-Race", "Infra-PerCommit-Small"].
	// buildsToTags is the map of which tags to use when scheduling
	// some of the builds. Eg: {"Infra-PerCommit-Race": {"triggered_by": "skcq"}}
	// means that the Infra-PerCommit-Race build should be scheduled with the
	// "triggered_by: skcq" tag.
	ScheduleBuilds(ctx context.Context, builds []string, buildsToTags map[string]map[string]string, issue, patchset int64, gerritUrl, repo, bbProject, bbBucket string) ([]*buildbucketpb.Build, error)
	// CancelBuilds cancels the specified buildIDs with the specified
	// summaryMarkdown. Builds are cancelled with one batch request
	// to buildbucket.
	CancelBuilds(ctx context.Context, buildIDs []int64, summaryMarkdown string) ([]*buildbucketpb.Build, error)
}

// Client is used for interacting with the BuildBucket API.
type Client struct {
	bc   buildbucketpb.BuildsClient
	host string
}

// NewClient returns an authenticated Client instance.
func NewClient(c *http.Client) *Client {
	host := DEFAULT_HOST
	return &Client{
		bc: buildbucketpb.NewBuildsPRPCClient(&prpc.Client{
			C:    c,
			Host: host,
		}),
		host: host,
	}
}

// NewTestingClient lets the MockClient inject a mock BuildsClient and host.
func NewTestingClient(bc buildbucketpb.BuildsClient, host string) *Client {
	return &Client{
		bc:   bc,
		host: host,
	}
}

// GetBuild implements the BuildBucketInterface.
func (c *Client) GetBuild(ctx context.Context, buildId int64) (*buildbucketpb.Build, error) {
	b, err := c.bc.GetBuild(ctx, &buildbucketpb.GetBuildRequest{
		Id:     buildId,
		Fields: common.GetBuildFields,
	})
	return b, err
}

// ScheduleBuilds implements the BuildBucketInterface.
func (c *Client) ScheduleBuilds(ctx context.Context, builds []string, buildsToTags map[string]map[string]string, issue, patchset int64, gerritURL, repo, bbProject, bbBucket string) ([]*buildbucketpb.Build, error) {
	requests := []*buildbucketpb.BatchRequest_Request{}
	for _, b := range builds {
		tagStringPairs := []*buildbucketpb.StringPair{}
		tags, ok := buildsToTags[b]
		if ok {
			for n, v := range tags {
				stringPair := &buildbucketpb.StringPair{
					Key:   n,
					Value: v,
				}
				tagStringPairs = append(tagStringPairs, stringPair)
			}
		}
		request := &buildbucketpb.BatchRequest_Request{
			Request: &buildbucketpb.BatchRequest_Request_ScheduleBuild{
				ScheduleBuild: &buildbucketpb.ScheduleBuildRequest{
					Builder: &buildbucketpb.BuilderID{
						Project: bbProject,
						Bucket:  bbBucket,
						Builder: b,
					},
					GerritChanges: []*buildbucketpb.GerritChange{
						{
							Host:     gerritURL,
							Project:  repo,
							Change:   issue,
							Patchset: patchset,
						},
					},
					Properties: &structpb.Struct{},
					Tags:       tagStringPairs,
					Fields:     common.GetBuildFields,
				},
			},
		}
		requests = append(requests, request)
	}

	resp, err := c.bc.Batch(ctx, &buildbucketpb.BatchRequest{
		Requests: requests,
	})
	if err != nil {
		return nil, skerr.Fmt("Could not schedule builds on buildbucket: %s", err)
	}
	if len(resp.Responses) != len(builds) {
		return nil, skerr.Fmt("Buildbucket gave %d responses for %d builders", len(resp.Responses), len(builds))
	}

	respBuilds := []*buildbucketpb.Build{}
	for _, r := range resp.Responses {
		respBuilds = append(respBuilds, r.GetScheduleBuild())
	}
	return respBuilds, nil
}

// CancelBuilds implements the BuildBucketInterface.
func (c *Client) CancelBuilds(ctx context.Context, buildIDs []int64, summaryMarkdown string) ([]*buildbucketpb.Build, error) {
	requests := []*buildbucketpb.BatchRequest_Request{}
	for _, bID := range buildIDs {
		request := &buildbucketpb.BatchRequest_Request{
			Request: &buildbucketpb.BatchRequest_Request_CancelBuild{
				CancelBuild: &buildbucketpb.CancelBuildRequest{
					Id:              bID,
					SummaryMarkdown: summaryMarkdown,
				},
			},
		}
		requests = append(requests, request)
	}

	resp, err := c.bc.Batch(ctx, &buildbucketpb.BatchRequest{
		Requests: requests,
	})
	if err != nil {
		return nil, skerr.Wrapf(err, "Could not cancel builds on buildbucket")
	}
	if len(resp.Responses) != len(buildIDs) {
		return nil, skerr.Fmt("Buildbucket gave %d responses for %d builders", len(resp.Responses), len(buildIDs))
	}

	respBuilds := []*buildbucketpb.Build{}
	for _, r := range resp.Responses {
		respBuilds = append(respBuilds, r.GetCancelBuild())
	}
	return respBuilds, nil
}

// GetBuild implements the BuildBucketInterface.
func (c *Client) Search(ctx context.Context, pred *buildbucketpb.BuildPredicate) ([]*buildbucketpb.Build, error) {
	rv := []*buildbucketpb.Build{}
	cursor := ""
	for {
		req := &buildbucketpb.SearchBuildsRequest{
			Fields:    common.SearchBuildsFields,
			PageToken: cursor,
			Predicate: pred,
		}
		resp, err := c.bc.SearchBuilds(ctx, req)
		if err != nil {
			return nil, err
		}
		if resp == nil {
			break
		}
		rv = append(rv, resp.Builds...)
		cursor = resp.NextPageToken
		if cursor == "" {
			break
		}
	}
	return rv, nil
}

// GetTrybotsForCL implements the BuildBucketInterface.
func (c *Client) GetTrybotsForCL(ctx context.Context, issue, patchset int64, gerritUrl string, tags map[string]string) ([]*buildbucketpb.Build, error) {
	pred, err := common.GetTrybotsForCLPredicate(issue, patchset, gerritUrl, tags)
	if err != nil {
		return nil, err
	}
	return c.Search(ctx, pred)
}

// Make sure Client fulfills the BuildBucketInterface interface.
var _ BuildBucketInterface = (*Client)(nil)
