package blesser

import (
	"encoding/json"
	"fmt"
	"net/http"
	"strings"
	"time"

	"veyron/services/identity"
	"veyron/services/identity/googleoauth"
	"veyron2"
	"veyron2/ipc"
	"veyron2/vdl/vdlutil"
	"veyron2/vlog"
)

type googleOAuth struct {
	rt                veyron2.Runtime
	authcodeClient    struct{ ID, Secret string }
	accessTokenClient struct{ ID string }
	duration          time.Duration
	domain            string
}

// GoogleParams represents all the parameters provided to NewGoogleOAuthBlesserServer
type GoogleParams struct {
	// The Veyron runtime to use
	R veyron2.Runtime
	// The OAuth client ID and secret for clients of the BlessUsingAuthorizationCode RPC
	AuthorizationCodeClient struct {
		ID, Secret string
	}
	// The OAuth client ID for the chrome-extension that will make BlessUsingAccessToken RPCs.
	AccessTokenClient struct {
		ID string
	}
	// The duration for which blessings will be valid.
	BlessingDuration time.Duration
	// If non-empty, only email addresses from this domain will be blessed.
	DomainRestriction string
}

// NewGoogleOAuthBlesserServer provides an identity.OAuthBlesserService that uses authorization
// codes to obtain the username of a client and provide blessings with that name.
//
// For more details, see documentation on Google OAuth 2.0 flows:
// https://developers.google.com/accounts/docs/OAuth2
//
// Blessings generated by this server expire after duration. If domain is non-empty, then blessings
// are generated only for email addresses from that domain.
func NewGoogleOAuthBlesserServer(p GoogleParams) interface{} {
	b := &googleOAuth{
		rt:       p.R,
		duration: p.BlessingDuration,
		domain:   p.DomainRestriction,
	}
	b.authcodeClient.ID = p.AuthorizationCodeClient.ID
	b.authcodeClient.Secret = p.AuthorizationCodeClient.Secret
	b.accessTokenClient.ID = p.AccessTokenClient.ID
	return identity.NewServerOAuthBlesser(b)
}

func (b *googleOAuth) BlessUsingAuthorizationCode(ctx ipc.ServerContext, authcode, redirectURL string) (vdlutil.Any, error) {
	if len(b.authcodeClient.ID) == 0 {
		return nil, fmt.Errorf("server not configured for blessing based on authorization codes")
	}
	config := googleoauth.NewOAuthConfig(b.authcodeClient.ID, b.authcodeClient.Secret, redirectURL)
	name, err := googleoauth.ExchangeAuthCodeForEmail(config, authcode)
	if err != nil {
		return nil, err
	}
	return b.bless(ctx, name)
}

func (b *googleOAuth) BlessUsingAccessToken(ctx ipc.ServerContext, accesstoken string) (vdlutil.Any, error) {
	if len(b.accessTokenClient.ID) == 0 {
		return nil, fmt.Errorf("server not configured for blessing based on access tokens")
	}
	// URL from: https://developers.google.com/accounts/docs/OAuth2UserAgent#validatetoken
	tokeninfo, err := http.Get("https://www.googleapis.com/oauth2/v1/tokeninfo?access_token=" + accesstoken)
	if err != nil {
		return nil, fmt.Errorf("unable to use token: %v", err)
	}
	if tokeninfo.StatusCode != http.StatusOK {
		return nil, fmt.Errorf("unable to verify access token: %v", tokeninfo.StatusCode)
	}
	// tokeninfo contains a JSON-encoded struct
	var token struct {
		IssuedTo      string `json:"issued_to"`
		Audience      string `json:"audience"`
		UserID        string `json:"user_id"`
		Scope         string `json:"scope"`
		ExpiresIn     int64  `json:"expires_in"`
		Email         string `json:"email"`
		VerifiedEmail bool   `json:"verified_email"`
		AccessType    string `json:"access_type"`
	}
	if err := json.NewDecoder(tokeninfo.Body).Decode(&token); err != nil {
		return "", fmt.Errorf("invalid JSON response from Google's tokeninfo API: %v", err)
	}
	if token.Audience != b.accessTokenClient.ID {
		vlog.Infof("Got access token [%+v], wanted client id %v", token, b.accessTokenClient.ID)
		return "", fmt.Errorf("token not meant for this purpose, confused deputy? https://developers.google.com/accounts/docs/OAuth2UserAgent#validatetoken")
	}
	if !token.VerifiedEmail {
		return nil, fmt.Errorf("email not verified")
	}
	return b.bless(ctx, token.Email)
}

func (b *googleOAuth) bless(ctx ipc.ServerContext, name string) (vdlutil.Any, error) {
	if len(b.domain) > 0 && !strings.HasSuffix(name, "@"+b.domain) {
		return nil, fmt.Errorf("blessings for %q are not allowed", name)
	}
	self := b.rt.Identity()
	var err error
	// Use the blessing that was used to authenticate with the client to bless it.
	if self, err = self.Derive(ctx.LocalID()); err != nil {
		return nil, err
	}
	// TODO(ashankar,ataly): Use the same set of caveats as is used by the HTTP handler.
	// For example, a third-party revocation caveat?
	return self.Bless(ctx.RemoteID(), name, b.duration, nil)
}
