// Copyright 2014 The Go Authors. All rights reserved.
// Use of this source code is governed by a BSD-style
// license that can be found in the LICENSE file.

package passwordcredentials

import (
	"fmt"
	"io/ioutil"
	"net/http"
	"net/http/httptest"
	"testing"

	"golang.org/x/oauth2"
)

func newConf(url string) *Config {
	return &Config{
		ClientID:     "CLIENT_ID",
		ClientSecret: "CLIENT_SECRET",
		Username:     "USERNAME",
		Password:     "PASSWORD",
		Scopes:       []string{"scope1", "scope2"},
		Endpoint: oauth2.Endpoint{
			TokenURL: url + "/token",
		},
	}
}

const stubAccessToken = "90d64460d14870c08c81352a05dedd3465940a7c"

type mockTransport struct {
	rt func(req *http.Request) (resp *http.Response, err error)
}

func (t *mockTransport) RoundTrip(req *http.Request) (resp *http.Response, err error) {
	return t.rt(req)
}

func TestTokenRequest(t *testing.T) {
	ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		if r.URL.String() != "/token" {
			t.Errorf("authenticate client request URL = %q; want %q", r.URL, "/token")
		}
		headerAuth := r.Header.Get("Authorization")
		if headerAuth != "Basic Q0xJRU5UX0lEOkNMSUVOVF9TRUNSRVQ=" {
			t.Errorf("Unexpected authorization header, %v is found.", headerAuth)
		}
		if got, want := r.Header.Get("Content-Type"), "application/x-www-form-urlencoded"; got != want {
			t.Errorf("Content-Type header = %q; want %q", got, want)
		}
		body, err := ioutil.ReadAll(r.Body)
		if err != nil {
			r.Body.Close()
		}
		if err != nil {
			t.Errorf("failed reading request body: %s.", err)
		}
		want := "client_id=CLIENT_ID&grant_type=password&password=PASSWORD&scope=scope1+scope2&username=USERNAME"
		if string(body) != want {
			t.Errorf("payload = %q; want %q", string(body), want)
		}
		w.Header().Set("Content-Type", "application/x-www-form-urlencoded")
		w.Write([]byte(fmt.Sprintf("access_token=%s&token_type=bearer", stubAccessToken)))
	}))
	defer ts.Close()
	conf := newConf(ts.URL)
	tok, err := conf.TokenSource(oauth2.NoContext).Token()
	if err != nil {
		t.Error(err)
	}
	if !tok.Valid() {
		t.Fatalf("token invalid. got: %#v", tok)
	}
	if tok.AccessToken != stubAccessToken {
		t.Errorf("Access token = %q; want %q", tok.AccessToken, stubAccessToken)
	}
	if tok.TokenType != "bearer" {
		t.Errorf("token type = %q; want %q", tok.TokenType, "bearer")
	}
}

func TestTokenRefreshRequest(t *testing.T) {
	ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		if r.URL.String() == "/somethingelse" {
			return
		}
		if r.URL.String() != "/token" {
			t.Errorf("Unexpected token refresh request URL, %v is found.", r.URL)
		}
		headerContentType := r.Header.Get("Content-Type")
		if headerContentType != "application/x-www-form-urlencoded" {
			t.Errorf("Unexpected Content-Type header, %v is found.", headerContentType)
		}
		body, _ := ioutil.ReadAll(r.Body)
		want := "client_id=CLIENT_ID&grant_type=password&password=PASSWORD&scope=scope1+scope2&username=USERNAME"
		if string(body) != want {
			t.Errorf("payload = %q; want %q", string(body), want)
		}
	}))
	defer ts.Close()
	conf := newConf(ts.URL)
	c := conf.Client(oauth2.NoContext)
	c.Get(ts.URL + "/somethingelse")
}
