package auth

import (
	"context"
	"encoding/json"
	"io"
	"net/http"
	"path/filepath"
	"time"

	gstorage "cloud.google.com/go/storage"
	"golang.org/x/oauth2"

	"go.skia.org/infra/go/auth"
	"go.skia.org/infra/go/fileutil"
	"go.skia.org/infra/go/httputils"
	"go.skia.org/infra/go/luciauth"
	"go.skia.org/infra/go/skerr"
	"go.skia.org/infra/go/util"
	"go.skia.org/infra/gold-client/go/gcsuploader"
	"go.skia.org/infra/gold-client/go/httpclient"
	"go.skia.org/infra/gold-client/go/imagedownloader"
)

const (
	// authFile is the file in the work directory where the auth options are cached.
	authFile = "auth_opt.json"

	defaultDialTimeout    = 3 * time.Second
	defaultRequestTimeout = 10 * time.Second
)

// The AuthOpt interface adds a layer of abstraction around getting authenticated
// clients that can make certain requests over the wire.
// This being an interface makes for easier mocking than just the raw struct.
type AuthOpt interface {
	// Validate returns an error if this is not a valid authenticated interface nil, otherwise.
	Validate() error
	// GetHTTPClient returns an authenticated goldclient.HTTPClient (which for non-mocked
	// implementations will be an http.Client)
	GetHTTPClient() (httpclient.HTTPClient, error)
	// SetDryRun will toggle actually uploading to GCS or not. This should be set before
	// any calls to GetGCSUploader
	SetDryRun(isDryRun bool)
	// GetGCSUploader returns an authenticated goldclient.GCSUploader, the interface for
	// uploading to GCS.
	GetGCSUploader(context.Context) (gcsuploader.GCSUploader, error)

	// GetImageDownloader returns an authenticated goldclient.ImageDownloader, the interface for
	// downloading from GCS.
	GetImageDownloader() (imagedownloader.ImageDownloader, error)
}

// authOpt implements the AuthOpt interface
type authOpt struct {
	Luci           bool
	ServiceAccount string
	GSUtil         bool
	NoAuth         bool // skbug.com/14142

	dryRun bool // unexported, i.e. not saved to JSON
}

// Validate implements the AuthOpt interface.
func (a *authOpt) Validate() error {
	if !a.GSUtil && !a.Luci && a.ServiceAccount == "" && !a.NoAuth {
		return skerr.Fmt("No valid authentication method provided.")
	}
	return nil
}

func nativeHTTPClient(ts oauth2.TokenSource) *http.Client {
	return httputils.ClientConfig{
		DialTimeout:    defaultDialTimeout,
		RequestTimeout: defaultRequestTimeout,
		TokenSource:    ts,
		// Don't configure retries here but in goldclient/common
		// so we can retry if there is an EOF error as well as a
		// bad response code.
		Retries:           nil,
		Metrics:           false,
		Response2xxOnly:   false,
		Response2xxAnd3xx: false,
	}.Client()
}

// GetHTTPClient implements the AuthOpt interface.
func (a *authOpt) GetHTTPClient() (httpclient.HTTPClient, error) {
	if a.GSUtil || a.NoAuth {
		return httpclient.WrapNative(nativeHTTPClient(nil)), nil
	}
	var tokenSrc oauth2.TokenSource
	if a.Luci {
		var err error
		tokenSrc, err = luciauth.NewLUCIContextTokenSource(gstorage.ScopeFullControl, auth.ScopeUserinfoEmail)
		if err != nil {
			return nil, skerr.Wrapf(err, "instantiating LUCI auth token source")
		}
	} else {
		var err error
		tokenSrc, err = auth.NewJWTServiceAccountTokenSource(context.TODO(), "", a.ServiceAccount, "", "", gstorage.ScopeFullControl, auth.ScopeUserinfoEmail)
		if err != nil {
			return nil, skerr.Wrapf(err, "instantiating JWT auth token source")
		}
	}

	// Retrieve a token to make sure we can retrieve a token. We assume this is cached
	// inside tokenSrc.
	if _, err := tokenSrc.Token(); err != nil {
		return nil, skerr.Wrapf(err, "retrieving initial auth token")
	}
	return httpclient.WrapNative(nativeHTTPClient(tokenSrc)), nil
}

// GetGCSUploader implements the AuthOpt interface.
func (a *authOpt) GetGCSUploader(ctx context.Context) (gcsuploader.GCSUploader, error) {
	if a.dryRun {
		return &gcsuploader.DryRunImpl{}, nil
	}
	if a.Luci || a.ServiceAccount != "" || a.NoAuth {
		return a.httpGCSImpl(ctx)
	}
	return &gcsuploader.GsutilImpl{}, nil
}

// GetImageDownloader implements the AuthOpt interface.
func (a *authOpt) GetImageDownloader() (imagedownloader.ImageDownloader, error) {
	if a.dryRun {
		return &imagedownloader.DryRunImpl{}, nil
	}
	hc, err := a.GetHTTPClient()
	if err != nil {
		return nil, skerr.Wrap(err)
	}
	return imagedownloader.New(hc), nil
}

func (a *authOpt) httpGCSImpl(ctx context.Context) (gcsuploader.GCSUploader, error) {
	if httpClient, err := a.GetHTTPClient(); err != nil {
		return nil, err
	} else {
		hc := httpclient.Unwrap(httpClient)
		if hc == nil {
			// Should never happen, but is easier to debug than a panic
			return nil, skerr.Fmt("HTTPClient was wrong type: %#v", httpClient)
		}
		return gcsuploader.New(ctx, hc)
	}
}

// SetDryRun implements the AuthOpt interface.
func (a *authOpt) SetDryRun(isDryRun bool) {
	a.dryRun = isDryRun
}

func (a *authOpt) writeToDisk(workDir string) error {
	outFile := filepath.Join(workDir, authFile)
	err := util.WithWriteFile(outFile, func(w io.Writer) error {
		return json.NewEncoder(w).Encode(a)
	})
	if err != nil {
		return skerr.Wrapf(err, "writing/serializing to JSON file %s", outFile)
	}
	return nil
}

// LoadAuthOpt will load a serialized *authOpt from disk and return it.
// If there is not one, it will return nil.
func LoadAuthOpt(workDir string) (*authOpt, error) {
	aFile := filepath.Join(workDir, authFile)
	if !fileutil.FileExists(aFile) {
		return nil, skerr.Fmt("File %s does not exist", aFile)
	}

	ret := &authOpt{}
	err := util.WithReadFile(aFile, func(r io.Reader) error {
		return json.NewDecoder(r).Decode(&ret)
	})
	if err != nil {
		return nil, skerr.Wrapf(err, "reading/parsing JSON file: %s", aFile)
	}

	return ret, nil
}

// InitServiceAccountAuth instantiates a workDir to be authenticated with the given
// serviceAccountFile.
func InitServiceAccountAuth(svcAccountFile, workDir string) error {
	a := authOpt{ServiceAccount: svcAccountFile}
	if err := a.writeToDisk(workDir); err != nil {
		return skerr.Wrapf(err, "writing to work dir: %s", workDir)
	}
	return nil
}

// InitLUCIAuth instantiates a workDir to be authenticated with LUCI
// credentials on this machine.
func InitLUCIAuth(workDir string) error {
	a := authOpt{Luci: true}
	if err := a.writeToDisk(workDir); err != nil {
		return skerr.Wrapf(err, "writing to work dir: %s", workDir)
	}
	return nil
}

// InitGSUtil instantiates a workDir to be authenticated with gsutil
// This is primarily used for local testing, and should not be relied
// upon for production usage.
func InitGSUtil(workDir string) error {
	a := authOpt{GSUtil: true}
	if err := a.writeToDisk(workDir); err != nil {
		return skerr.Wrapf(err, "writing to work dir: %s", workDir)
	}
	return nil
}

// InitNoAuth instantiates a workDir to use an unauthenticated HTTP client.
func InitNoAuth(workDir string) error {
	a := authOpt{NoAuth: true}
	if err := a.writeToDisk(workDir); err != nil {
		return skerr.Wrapf(err, "writing to work dir: %s", workDir)
	}
	return nil
}
