// Copyright 2020 The Fuchsia 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 main

import (
	"context"
	"errors"
	"fmt"

	"github.com/golang-collections/collections/set"
	"go.chromium.org/luci/auth"
	buildbucketpb "go.chromium.org/luci/buildbucket/proto"
	"go.chromium.org/luci/grpc/prpc"
	"google.golang.org/genproto/protobuf/field_mask"
)

// buildbucketClientWrapper provides utilities for interacting with Buildbucket.
type buildbucketClientWrapper struct {
	client buildbucketpb.BuildsClient
}

// newBuildbucketClient returns an authenticated buildbucketClientWrapper.
func newBuildbucketClient(ctx context.Context, authOpts auth.Options, host string) (*buildbucketClientWrapper, error) {
	authClient, err := auth.NewAuthenticator(ctx, auth.OptionalLogin, authOpts).Client()
	if err != nil {
		return nil, err
	}
	client := buildbucketpb.NewBuildsPRPCClient(&prpc.Client{
		C:    authClient,
		Host: host,
	})
	return &buildbucketClientWrapper{client: client}, nil
}

// GetBuilds gets the latest n successful builds for each input builder, from most to least recent.
// The response is in the same order as the order of the input builders.
func (c *buildbucketClientWrapper) GetBuilds(ctx context.Context, builders []*buildbucketpb.BuilderID, mask *field_mask.FieldMask, n int) ([][]*buildbucketpb.Build, error) {
	// Always grab input by default.
	mask.Paths = append(mask.Paths, "builds.*.input")
	// Construct requests to execute in batch.
	reqs := make([]*buildbucketpb.BatchRequest_Request, len(builders))
	for i, builder := range builders {
		reqs[i] = &buildbucketpb.BatchRequest_Request{
			Request: &buildbucketpb.BatchRequest_Request_SearchBuilds{
				SearchBuilds: &buildbucketpb.SearchBuildsRequest{
					Predicate: &buildbucketpb.BuildPredicate{
						Builder: builder,
						Status:  buildbucketpb.Status_SUCCESS,
					},
					Fields:   mask,
					PageSize: int32(n),
				},
			},
		}
	}
	batchResp, err := c.client.Batch(ctx, &buildbucketpb.BatchRequest{Requests: reqs})
	if err != nil {
		return nil, fmt.Errorf("failed to retrieve latest %d successful builds for %s: %w", n, builders, err)
	}
	builds := make([][]*buildbucketpb.Build, len(builders))
	for i, resp := range batchResp.Responses {
		switch resp.Response.(type) {
		case *buildbucketpb.BatchResponse_Response_SearchBuilds:
			builds[i] = resp.Response.(*buildbucketpb.BatchResponse_Response_SearchBuilds).SearchBuilds.Builds
		case *buildbucketpb.BatchResponse_Response_Error:
			return nil, fmt.Errorf("got batch response error: %s", resp.GetError().String())
		default:
			return nil, fmt.Errorf("unexpected response type: %T", resp.Response)
		}
	}
	return builds, nil
}

// accessorFunc accesses a value from a Build.
type accessorFunc func(*buildbucketpb.Build) any

// getLastKnownGood gets the latest common attribute from the input slices of builds.
func getLastKnownGood(builds [][]*buildbucketpb.Build, gitilesRef string, f accessorFunc) (any, error) {
	if len(builds) == 0 {
		return nil, errors.New("input builds is of length 0")
	}
	// Compute common attributes to all slices but the first.
	var commonAttrSet *set.Set
	for _, buildSlice := range builds[1:] {
		attrSet := set.New()
		for _, build := range buildSlice {
			buildAttr := f(build)
			// Skip nil attributes.
			if buildAttr != nil {
				attrSet.Insert(buildAttr)
			}
		}
		// Initialize set on first iteration.
		if commonAttrSet == nil {
			commonAttrSet = attrSet
			// Otherwise, take the intersection between this set and the common set.
		} else {
			commonAttrSet = attrSet.Intersection(commonAttrSet)
		}
	}

	// Iterate through the first slice, returning the first attribute match.
	for _, build := range builds[0] {
		// Skip non-matching refs.
		if gitilesRef != "" && gitilesRef != build.Input.GitilesCommit.Ref {
			continue
		}
		attr := f(build)
		// For length-1 inputs, the set is nil, so return the first build.
		if commonAttrSet == nil || commonAttrSet.Has(attr) {
			return attr, nil
		}
	}

	return nil, errors.New("no common last-known-good attribute found")
}
