func TestMailer(t *testing.T) {
	g := Goblin(t)

	g.Describe("Mailer", func() {
		pwreset.CreateLogger(pwreset.NewContextForEnvironment("test"))

		g.It("should read the required credentials", func() {
			creds := pwreset.ReadCredentials()

			g.Assert(creds != nil).IsTrue()

			value, err := creds.Get()

			g.Assert(err == nil).IsTrue()
			g.Assert(len(value.AccessKeyID)).Equal(20)
			g.Assert(len(value.SecretAccessKey)).Equal(40)
		})

		g.It("should create a session from valid credentials", func() {
			creds := pwreset.ReadCredentials()
			svc := pwreset.CreateSession(creds)

			g.Assert(svc != nil).IsTrue()
			// fmt.Println("svc: ", svc.Client)
			g.Assert(svc.Client != nil).IsTrue()
		})
	})
}
func main() {
	ctx := pwreset.ParseArgs()
	log := pwreset.CreateLogger(ctx)

	// start the service...
	log.Info("start services with context: ", ctx.ToMap())

	err := pwreset.StartServers(ctx)

	if err != nil {
		fmt.Println("error starting servers: ", err)
		panic(err)
	}
}
func TestContext(t *testing.T) {
	g := Goblin(t)

	g.Describe("Context", func() {
		pwreset.CreateLogger(pwreset.NewContextForEnvironment("test"))

		g.It("should create a context struct", func() {
			ctx := new(pwreset.Context)

			g.Assert(ctx.GetShutdownPort()).Equal(0)
		})

		g.It("should create a context struct with defaults set", func() {
			ctx := pwreset.NewDefaultContext()

			g.Assert(ctx.GetShutdownPort()).Equal(3019)

			hash := ctx.ToMap()

			g.Assert(hash != nil)

			if value, ok := hash["webroot"]; ok {
				g.Assert(value).Equal("public")
			}

			g.Assert(hash["baseport"]).Equal(3011)
			g.Assert(hash["shutdownPort"]).Equal(3019)
			g.Assert(hash["serverCount"]).Equal(1)
			g.Assert(hash["timeout"]).Equal(int64(600))
		})

		g.It("should create context from args", func() {
			ctx := pwreset.ParseArgs()

			g.Assert(ctx.GetShutdownPort()).Equal(3019)

			hash := ctx.ToMap()

			g.Assert(hash["baseport"]).Equal(3011)
			g.Assert(hash["shutdownPort"]).Equal(3019)
			g.Assert(hash["serverCount"]).Equal(1)
			g.Assert(hash["timeout"]).Equal(int64(600))
		})

	})
}
func TestHandlers(t *testing.T) {
	g := Goblin(t)

	g.Describe("Handlers", func() {
		log := pwreset.CreateLogger(pwreset.NewContextForEnvironment("test"))

		g.It("should have a status handler that returns a json status blob", func() {
			mux := http.NewServeMux()
			mux.HandleFunc("/status", pwreset.StatusHandler)

			server := negroni.New()
			server.UseHandler(mux)

			request, err := http.NewRequest("GET", "http://test.com/status", nil)
			if err != nil {
				panic(err)
			}

			recorder := httptest.NewRecorder()

			server.ServeHTTP(recorder, request)
			// fmt.Println( recorder.Body.String() )
			log.Info("status response: %s", recorder.Body.String())

			g.Assert(recorder.Code).Equal(200)
			g.Assert(recorder.Body != nil).IsTrue()

			wrapper := make(map[string]interface{})
			err = json.Unmarshal(recorder.Body.Bytes(), &wrapper)

			g.Assert(err == nil).IsTrue()
			status := wrapper["status"]
			g.Assert(status).Equal("ok")
		})

		g.It("should have a ping handler that returns pong", func() {
			mux := http.NewServeMux()
			mux.HandleFunc("/ping", pwreset.PingHandler)

			server := negroni.New()
			server.UseHandler(mux)

			request, err := http.NewRequest("GET", "http://test.com/ping", nil)
			if err != nil {
				panic(err)
			}

			recorder := httptest.NewRecorder()

			server.ServeHTTP(recorder, request)
			log.Info("status response: %s", recorder.Body.String())

			g.Assert(recorder.Code).Equal(200)
			g.Assert(recorder.Body != nil).IsTrue()
			g.Assert(recorder.Body.String()).Equal("pong\r\n")
		})

		g.It("should have an index handler that returns not found if path is unknown", func() {
			mux := http.NewServeMux()
			mux.HandleFunc("/", pwreset.IndexHandler)

			server := negroni.New()
			server.UseHandler(mux)

			request, err := http.NewRequest("GET", "http://test.com/bad-request-path", nil)
			if err != nil {
				panic(err)
			}

			recorder := httptest.NewRecorder()

			server.ServeHTTP(recorder, request)
			log.Info("status response: %s", recorder.Body.String())

			g.Assert(recorder.Code).Equal(404)
			g.Assert(recorder.Body != nil).IsTrue()
			g.Assert(recorder.Body.String()).Equal("404 page not found\n")
		})

		g.It("should have a shutdown handler that rejects shudown requests with GET", func() {
			mux := http.NewServeMux()
			mux.HandleFunc("/shutdown", pwreset.ShutdownHandler)

			server := negroni.New()
			server.UseHandler(mux)

			request, err := http.NewRequest("GET", "http://test.com/shutdown", nil)
			if err != nil {
				panic(err)
			}

			recorder := httptest.NewRecorder()

			server.ServeHTTP(recorder, request)
			log.Info("status response: %s", recorder.Body.String())

			g.Assert(recorder.Code).Equal(200)
			g.Assert(recorder.Body != nil).IsTrue()
			g.Assert(recorder.Body.String()).Equal("shutdown requested...\r\nshutdown request denied...\r\n")
		})

		g.It("should have a reset handler that rejects requests without key", func() {
			mux := http.NewServeMux()
			mux.HandleFunc("/login", pwreset.ResetHandler)

			server := negroni.New()
			server.UseHandler(mux)

			request, err := http.NewRequest("POST", "http://test.com/login", nil)
			if err != nil {
				panic(err)
			}

			recorder := httptest.NewRecorder()

			server.ServeHTTP(recorder, request)
			log.Info("status response: %s", recorder.Body.String())

			g.Assert(recorder.Code).Equal(404)
			g.Assert(recorder.Body != nil).IsTrue()
			g.Assert(recorder.Body.String()).Equal("404 page not found\n")
		})

	})
}
func TestMiddleware(t *testing.T) {
	g := Goblin(t)

	g.Describe("Middleware", func() {
		pwreset.CreateLogger(pwreset.NewContextForEnvironment("test"))

		g.It("should accept a https proto request", func() {
			msg := "write success to service"
			recorder := httptest.NewRecorder()

			proto := pwreset.NewProtoMiddleware("production")

			server := negroni.New()
			server.Use(proto)

			server.UseHandler(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
				// fmt.Println( req.Header.Get("X-Forwarded-Proto"))
				fmt.Fprintf(w, msg)
			}))

			request, err := http.NewRequest("GET", "https://bluelasso.com/mypage", nil)
			request.Header.Set("X-Forwarded-Proto", "https")

			g.Assert(err == nil).IsTrue()

			server.ServeHTTP(recorder, request)

			// fmt.Printf("%d - %s", recorder.Code, recorder.Body.String())
			g.Assert(recorder.Code).Equal(200)
			g.Assert(recorder.Body.String()).Equal(msg)
		})

		g.It("should reject a non-https request", func() {
			msg := "write success to service"
			recorder := httptest.NewRecorder()

			proto := pwreset.NewProtoMiddleware("production")

			server := negroni.New()
			server.Use(proto)

			server.UseHandler(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
				// fmt.Println( req.Header.Get("X-Forwarded-Proto"))
				fmt.Fprintf(w, msg)
			}))

			request, err := http.NewRequest("GET", "https://bluelasso.com/mypage", nil)
			request.Header.Set("X-Forwarded-Proto", "http")

			g.Assert(err == nil).IsTrue()

			server.ServeHTTP(recorder, request)

			// fmt.Printf("%d - %s", recorder.Code, recorder.Body.String())
			g.Assert(recorder.Code).Equal(200)
			g.Assert(recorder.Body.String() != msg)
		})

		g.It("should accept a non-https request for status", func() {
			msg := "write success to service for status"
			recorder := httptest.NewRecorder()

			proto := pwreset.NewProtoMiddleware("production")

			server := negroni.New()
			server.Use(proto)

			server.UseHandler(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
				// fmt.Println( req.Header.Get("X-Forwarded-Proto"))
				fmt.Fprintf(w, msg)
			}))

			request, err := http.NewRequest("GET", "https://bluelasso.com/status", nil)
			request.Header.Set("X-Forwarded-Proto", "http")

			g.Assert(err == nil).IsTrue()

			server.ServeHTTP(recorder, request)

			g.Assert(recorder.Code).Equal(200)
			g.Assert(recorder.Body.String()).Equal(msg)
		})

		g.It("should accept a non-https request for ping", func() {
			msg := "write success to service for ping"
			recorder := httptest.NewRecorder()

			proto := pwreset.NewProtoMiddleware("production")

			server := negroni.New()
			server.Use(proto)

			server.UseHandler(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
				// fmt.Println( req.Header.Get("X-Forwarded-Proto"))
				fmt.Fprintf(w, msg)
			}))

			request, err := http.NewRequest("GET", "https://bluelasso.com/ping", nil)
			request.Header.Set("X-Forwarded-Proto", "http")

			g.Assert(err == nil).IsTrue()

			server.ServeHTTP(recorder, request)

			g.Assert(recorder.Code).Equal(200)
			g.Assert(recorder.Body.String()).Equal(msg)
		})

		g.It("should accept a non-https request for non-production", func() {
			msg := "write success to service for non-production env"
			recorder := httptest.NewRecorder()

			proto := pwreset.NewProtoMiddleware("test")

			server := negroni.New()
			server.Use(proto)

			server.UseHandler(http.HandlerFunc(func(w http.ResponseWriter, req *http.Request) {
				// fmt.Println( req.Header.Get("X-Forwarded-Proto"))
				fmt.Fprintf(w, msg)
			}))

			request, err := http.NewRequest("GET", "https://bluelasso.com/anypage", nil)
			request.Header.Set("X-Forwarded-Proto", "http")

			g.Assert(err == nil).IsTrue()

			server.ServeHTTP(recorder, request)

			g.Assert(recorder.Code).Equal(200)
			g.Assert(recorder.Body.String()).Equal(msg)
		})
	})
}