// Copyright 2016 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 gaeconfig

import (
	"context"
	"fmt"
	"net/http"
	"os"
	"path/filepath"

	"google.golang.org/grpc/credentials"

	"go.chromium.org/luci/common/errors"
	"go.chromium.org/luci/gae/service/info"
	"go.chromium.org/luci/server/auth"

	"go.chromium.org/luci/config"
	"go.chromium.org/luci/config/cfgclient"
	"go.chromium.org/luci/config/impl/erroring"
	"go.chromium.org/luci/config/vars"
)

// devCfgDir is a name of the directory with config files when running in
// local dev appserver model. See Use for details.
const devCfgDir = "devcfg"

// defaultLazyConfigClient is the lazyConfigClient that will be shared by
// all requests.
var defaultLazyConfigClient = newLazyConfigClient(func(ctx context.Context) config.Interface {
	return newClientFromSettings(ctx, mustFetchCachedSettings(ctx))
})

// Use installs the default luci-config client.
//
// The client is configured to use luci-config URL specified in the settings,
// using GAE app service account for authentication.
//
// If running in prod, and the settings don't specify luci-config URL, produces
// an implementation that returns a "not configured" error from all methods.
//
// If running on devserver, and the settings don't specify luci-config URL,
// returns a filesystem-based implementation that reads configs from a directory
// (or a symlink) named 'devcfg' located in the GAE module directory (where
// app.yaml is) or its immediate parent directory.
//
// If such directory can not be located, produces an implementation of that
// returns errors from all methods.
//
// Panics if it can't load the settings (should not happen since they are in
// the local memory cache usually).
func Use(ctx context.Context) context.Context {
	return cfgclient.Use(ctx, defaultLazyConfigClient)
}

// devServerConfigsDir finds a directory with configs to use on the dev server.
func devServerConfigsDir() (string, error) {
	pwd := os.Getenv("PWD") // os.Getwd works funny with symlinks, use PWD
	candidates := []string{
		filepath.Join(pwd, devCfgDir),
		filepath.Join(filepath.Dir(pwd), devCfgDir),
	}
	for _, dir := range candidates {
		if _, err := os.Stat(dir); err == nil {
			return dir, nil
		}
	}
	return "", fmt.Errorf("luci-config: could not find local configs in any of %s", candidates)
}

// newClientFromSettings instantiates a LUCI Config client based on settings.
func newClientFromSettings(c context.Context, s *Settings) config.Interface {
	var configsDir string
	if s.ConfigServiceHost == "" && info.IsDevAppServer(c) {
		var err error
		if configsDir, err = devServerConfigsDir(); err != nil {
			return erroring.New(err)
		}
	}

	client, err := cfgclient.New(c, cfgclient.Options{
		Vars:        &vars.Vars,
		ServiceHost: s.ConfigServiceHost,
		ConfigsDir:  configsDir,
		ClientFactory: func(ctx context.Context) (*http.Client, error) {
			t, err := auth.GetRPCTransport(ctx, auth.AsSelf, auth.WithScopes(auth.CloudOAuthScopes...))
			if err != nil {
				return nil, err
			}
			return &http.Client{Transport: t}, nil
		},
		GetPerRPCCredsFn: func(ctx context.Context) (credentials.PerRPCCredentials, error) {
			creds, err := auth.GetPerRPCCredentials(ctx,
				auth.AsSelf,
				auth.WithIDTokenAudience("https://"+s.ConfigServiceHost),
			)
			if err != nil {
				return nil, errors.Annotate(err, "failed to get credentials to access %s", s.ConfigServiceHost).Err()
			}
			return creds, nil
		},
		UserAgent: info.AppID(c),
	})
	if err != nil {
		return erroring.New(err)
	}
	return client
}
