// Copyright 2020 The LUCI Authors.
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//      http://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

package gerrit

import (
	"context"
	"net/http"
	"strings"
	"time"

	"golang.org/x/oauth2"

	luciauth "go.chromium.org/luci/auth"
	"go.chromium.org/luci/common/api/gerrit"
	"go.chromium.org/luci/common/errors"
	"go.chromium.org/luci/server/auth"
)

// prodFactory knows how to construct Gerrit clients and hop over Gerrit
// mirrors.
type prodFactory struct {
	baseTransport http.RoundTripper

	mirrorHostPrefixes []string

	mockMintProjectToken func(context.Context, auth.ProjectTokenParams) (*auth.Token, error)
}

var errEmptyProjectToken = errors.New("crbug/824492: Project token is empty")

func newProd(ctx context.Context, mirrorHostPrefixes ...string) (*prodFactory, error) {
	t, err := auth.GetRPCTransport(ctx, auth.NoAuth)
	if err != nil {
		return nil, err
	}
	return &prodFactory{
		baseTransport:      t,
		mirrorHostPrefixes: mirrorHostPrefixes,
	}, nil
}

// MakeMirrorIterator implements Factory.
func (p *prodFactory) MakeMirrorIterator(ctx context.Context) *MirrorIterator {
	return newMirrorIterator(ctx, p.mirrorHostPrefixes...)
}

// MakeClient implements Factory.
func (f *prodFactory) MakeClient(ctx context.Context, gerritHost, luciProject string) (Client, error) {
	if strings.ContainsRune(luciProject, '.') {
		panic(errors.Reason("swapped host %q with luciProject %q", gerritHost, luciProject).Err())
	}
	// TODO(crbug/824492): use auth.GetRPCTransport(ctx, auth.AsProject, ...)
	// directly after pssa migration is over. Currently, we need a special
	// error to detect whether pssa is configured or not.
	t, err := f.transport(gerritHost, luciProject)
	if err != nil {
		return nil, err
	}
	return gerrit.NewRESTClient(&http.Client{Transport: t}, gerritHost, true)
}

func (f *prodFactory) transport(gerritHost, luciProject string) (http.RoundTripper, error) {
	return luciauth.NewModifyingTransport(f.baseTransport, func(req *http.Request) error {
		tok, err := f.token(req.Context(), gerritHost, luciProject)
		if err != nil {
			return err
		}
		req.Header.Set("Authorization", tok.TokenType+" "+tok.AccessToken)
		return nil
	}), nil
}

func (f *prodFactory) token(ctx context.Context, gerritHost, luciProject string) (*oauth2.Token, error) {
	req := auth.ProjectTokenParams{
		MinTTL:      2 * time.Minute,
		LuciProject: luciProject,
		OAuthScopes: []string{gerrit.OAuthScope},
	}
	mintToken := auth.MintProjectToken
	if f.mockMintProjectToken != nil {
		mintToken = f.mockMintProjectToken
	}
	switch token, err := mintToken(ctx, req); {
	case err != nil:
		return nil, err
	case token == nil:
		return nil, errors.Annotate(errEmptyProjectToken, "LUCI project: %q", luciProject).Err()
	default:
		return &oauth2.Token{
			AccessToken: token.Token,
			TokenType:   "Bearer",
		}, nil
	}
}
