package apidApigeeSync

import (
	"time"

	"net/http"
	"net/http/httptest"

	"encoding/json"

	. "github.com/onsi/ginkgo"
	. "github.com/onsi/gomega"
)

var _ = Describe("token", func() {

	Context("oauthToken", func() {

		It("should calculate valid token", func() {
			log.Info("Starting token tests...")

			t := &oauthToken{
				AccessToken: "x",
				ExpiresIn:   120000,
				ExpiresAt:   time.Now().Add(2 * time.Minute),
			}
			Expect(t.refreshIn().Seconds()).To(BeNumerically(">", 0))
			Expect(t.needsRefresh()).To(BeFalse())
			Expect(t.isValid()).To(BeTrue())
		})

		It("should calculate expired token", func() {

			t := &oauthToken{
				AccessToken: "x",
				ExpiresIn:   0,
				ExpiresAt:   time.Now(),
			}
			Expect(t.refreshIn().Seconds()).To(BeNumerically("<", 0))
			Expect(t.needsRefresh()).To(BeTrue())
			Expect(t.isValid()).To(BeFalse())
		})

		It("should calculate token needing refresh", func() {

			t := &oauthToken{
				AccessToken: "x",
				ExpiresIn:   59000,
				ExpiresAt:   time.Now().Add(time.Minute - time.Second),
			}
			Expect(t.refreshIn().Seconds()).To(BeNumerically("<", 0))
			Expect(t.needsRefresh()).To(BeTrue())
			Expect(t.isValid()).To(BeTrue())
		})

		It("should calculate on empty token", func() {

			t := &oauthToken{}
			Expect(t.refreshIn().Seconds()).To(BeNumerically("<=", 0))
			Expect(t.needsRefresh()).To(BeTrue())
			Expect(t.isValid()).To(BeFalse())
		})
	})

	Context("tokenMan", func() {

		It("should get a valid token", func() {

			tokenManager = createTokenManager()
			token := tokenManager.getToken()

			Expect(token.AccessToken).ToNot(BeEmpty())
			Expect(token.ExpiresIn > 0).To(BeTrue())
			Expect(token.ExpiresAt).To(BeTemporally(">", time.Now()))

			bToken := tokenManager.getBearerToken()
			Expect(bToken).To(Equal(token.AccessToken))
			tokenManager.close()
			//sleep to ensure tokenManager has closed.  t.close() is non blocking
			time.Sleep(500 * time.Millisecond)
		})

		It("should refresh when forced to", func() {

			tokenManager = createTokenManager()

			token := tokenManager.getToken()
			Expect(token.AccessToken).ToNot(BeEmpty())

			tokenManager.invalidateToken()

			token2 := tokenManager.getToken()
			Expect(token).ToNot(Equal(token2))
			Expect(token.AccessToken).ToNot(Equal(token2.AccessToken))
			tokenManager.close()
			//sleep to ensure tokenManager has closed.  t.close() is non blocking
			time.Sleep(500 * time.Millisecond)
		})

		It("should refresh in refresh interval", func(done Done) {

			finished := make(chan bool, 1)
			start := time.Now()
			count := 0
			ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
				defer GinkgoRecover()

				count++
				if count > 1 {
					if start.Add(500).After(time.Now()) {
						Fail("didn't refresh within expected interval")
					}
					finished <- true
				}

				res := oauthToken{
					AccessToken: string(count),
					ExpiresIn:   1000,
				}
				body, err := json.Marshal(res)
				Expect(err).NotTo(HaveOccurred())
				w.Write(body)
			}))

			config.Set(configProxyServerBaseURI, ts.URL)
			tokenManager = createTokenManager()

			tokenManager.getToken()

			oldFloat := refreshFloatTime
			refreshFloatTime = 950 * time.Millisecond
			defer func() {
				refreshFloatTime = oldFloat
			}()

			<-finished
			tokenManager.close()
			//sleep to ensure tokenManager has closed.  t.close() is non blocking
			time.Sleep(500 * time.Millisecond)
			ts.Close()

			close(done)
		})

		It("should have created_at_apid first time, update_at_apid after", func(done Done) {
			finished := make(chan bool, 1)
			count := 0

			newInstanceID = true

			ts := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {

				count++
				if count == 1 {
					Expect(newInstanceID).To(BeTrue())
					Expect(r.Header.Get("created_at_apid")).NotTo(BeEmpty())
					Expect(r.Header.Get("updated_at_apid")).To(BeEmpty())
				} else {
					Expect(newInstanceID).To(BeFalse())
					Expect(r.Header.Get("created_at_apid")).To(BeEmpty())
					Expect(r.Header.Get("updated_at_apid")).NotTo(BeEmpty())
					finished <- true
				}
				res := oauthToken{
					AccessToken: string(count),
				 	ExpiresIn:   200000,
				}
				body, err := json.Marshal(res)
				Expect(err).NotTo(HaveOccurred())
				w.Write(body)
			}))

			config.Set(configProxyServerBaseURI, ts.URL)
			tokenManager = createTokenManager()

			tokenManager.getToken()
			tokenManager.invalidateToken()
			tokenManager.getToken()
			<-finished
			tokenManager.close()
			//sleep to ensure tokenManager has closed.  t.close() is non blocking
			time.Sleep(500 * time.Millisecond)
			ts.Close()
			close(done)
		})
	})
})
