package firebase

import (
	"bytes"
	"context"
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"testing"

	firebase "firebase.google.com/go"
	"firebase.google.com/go/auth"
	"google.golang.org/api/option"
)

func TestUserIDToken(t *testing.T) {

	ctx := context.Background()

	opt := option.WithCredentialsFile("/Users/phongnguyen/Documents/startup/chonho.com/chonho-api/cho-nho-app-firebase-adminsdk-3jaz3-e76fb755e3.json")
	app, err := firebase.NewApp(ctx, nil, opt)

	client, err := app.Auth(ctx)
	if err != nil {
		t.Fatal(err)
	}

	user, err := client.CreateUser(ctx, (&auth.UserToCreate{}).Email("testuser@example.com"))
	if err != nil {
		t.Fatal(err)
	}

	tokenString, err := client.CustomToken(ctx, user.UID)
	if err != nil {
		t.Fatal(err)
	}

	idToken, err := signInWithCustomToken(tokenString)
	if err != nil {
		t.Fatal(err)
	}

	fmt.Printf("token: %s\n", idToken)

	token, err := client.VerifyIDToken(ctx, idToken)
	if err != nil {
		t.Fatal(err)
	}

	fmt.Printf("%+v\n", token)
}

const (
	verifyCustomTokenURL = "https://www.googleapis.com/identitytoolkit/v3/relyingparty/verifyCustomToken?key=%s"
)

var (
	apiKey = "AIzaSyBVZFLTXOk3BWShjny7K1_MVyhF0xcHlNI"
)

// see https://github.com/firebase/firebase-admin-go/blob/1d2a52c3c8195451b5ad2e0a173906bd6eb9529d/integration/auth/auth_test.go#L199
func signInWithCustomToken(token string) (string, error) {
	req, err := json.Marshal(map[string]interface{}{
		"token":             token,
		"returnSecureToken": true,
	})
	if err != nil {
		return "", err
	}

	resp, err := postRequest(fmt.Sprintf(verifyCustomTokenURL, apiKey), req)
	if err != nil {
		return "", err
	}
	var respBody struct {
		IDToken string `json:"idToken"`
	}
	if err := json.Unmarshal(resp, &respBody); err != nil {
		return "", err
	}
	return respBody.IDToken, err
}

func postRequest(url string, req []byte) ([]byte, error) {
	resp, err := http.Post(url, "application/json", bytes.NewBuffer(req))
	if err != nil {
		return nil, err
	}

	defer resp.Body.Close()
	if resp.StatusCode != http.StatusOK {
		return nil, fmt.Errorf("unexpected http status code: %d", resp.StatusCode)
	}
	return ioutil.ReadAll(resp.Body)
}
