package blesser

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

	"veyron.io/veyron/veyron/services/identity"
	"veyron.io/veyron/veyron/services/identity/revocation"

	"veyron.io/veyron/veyron2/ipc"
	"veyron.io/veyron/veyron2/security"
	"veyron.io/veyron/veyron2/vlog"
)

type googleOAuth struct {
	authcodeClient     struct{ ID, Secret string }
	accessTokenClients []string
	duration           time.Duration
	domain             string
	dischargerLocation string
	revocationManager  *revocation.RevocationManager
}

// GoogleParams represents all the parameters provided to NewGoogleOAuthBlesserServer
type GoogleParams struct {
	// The OAuth client IDs for the clients of the BlessUsingAccessToken RPCs.
	AccessTokenClients []string
	// If non-empty, only email addresses from this domain will be blessed.
	DomainRestriction string
	// The object name of the discharger service. If this is empty then revocation caveats will not be granted.
	DischargerLocation string
	// The revocation manager that generates caveats and manages revocation.
	RevocationManager *revocation.RevocationManager
	// The duration for which blessings will be valid. (Used iff RevocationManager is nil).
	BlessingDuration time.Duration
}

// 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{} {
	return identity.NewServerOAuthBlesser(&googleOAuth{
		duration:           p.BlessingDuration,
		domain:             p.DomainRestriction,
		dischargerLocation: p.DischargerLocation,
		revocationManager:  p.RevocationManager,
		accessTokenClients: p.AccessTokenClients,
	})
}

func (b *googleOAuth) BlessUsingAccessToken(ctx ipc.ServerContext, accesstoken string) (security.WireBlessings, string, error) {
	var noblessings security.WireBlessings
	if len(b.accessTokenClients) == 0 {
		return noblessings, "", 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 noblessings, "", fmt.Errorf("unable to use token: %v", err)
	}
	if tokeninfo.StatusCode != http.StatusOK {
		return noblessings, "", 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 noblessings, "", fmt.Errorf("invalid JSON response from Google's tokeninfo API: %v", err)
	}
	audienceMatch := false
	for _, c := range b.accessTokenClients {
		if token.Audience == c {
			audienceMatch = true
			break
		}
	}
	if !audienceMatch {
		vlog.Infof("Got access token [%+v], wanted one of client ids %v", token, b.accessTokenClients)
		return noblessings, "", fmt.Errorf("token not meant for this purpose, confused deputy? https://developers.google.com/accounts/docs/OAuth2UserAgent#validatetoken")
	}
	if !token.VerifiedEmail {
		return noblessings, "", fmt.Errorf("email not verified")
	}
	// Append "/webapp" to the blessing. Since blessings issued by this process do not have
	// many caveats on them and typically have a large expiry duration, use the "/webapp" suffix
	// so that at least any logs call out the fact that this is a webapp (and ACLs can be used
	// to kill authorization for them).
	return b.bless(ctx, token.Email+security.ChainSeparator+"webapp")
}

func (b *googleOAuth) bless(ctx ipc.ServerContext, extension string) (security.WireBlessings, string, error) {
	var noblessings security.WireBlessings
	self := ctx.LocalPrincipal()
	if self == nil {
		return noblessings, "", fmt.Errorf("server error: no authentication happened")
	}
	var caveat security.Caveat
	var err error
	if b.revocationManager != nil {
		revocationCaveat, err := b.revocationManager.NewCaveat(self.PublicKey(), b.dischargerLocation)
		if err != nil {
			return noblessings, "", err
		}
		caveat, err = security.NewCaveat(revocationCaveat)
	} else {
		caveat, err = security.ExpiryCaveat(time.Now().Add(b.duration))
	}
	if err != nil {
		return noblessings, "", err
	}
	blessing, err := self.Bless(ctx.RemoteBlessings().PublicKey(), ctx.LocalBlessings(), extension, caveat)
	if err != nil {
		return noblessings, "", err
	}
	return security.MarshalBlessings(blessing), extension, nil
}
