// Package oauthserver is a very simplistic OAuth server used only for
// the testing of the "terraform login" and "terraform logout" commands.
package oauthserver

import (
	"crypto/sha256"
	"encoding/base64"
	"fmt"
	"html"
	"log"
	"net/http"
	"net/url"
	"strings"
)

// Handler is an implementation of net/http.Handler that provides a stub
// OAuth server implementation with the following endpoints:
//
//     /authz  - authorization endpoint
//     /token  - token endpoint
//     /revoke - token revocation (logout) endpoint
//
// The authorization endpoint returns HTML per normal OAuth conventions, but
// it also includes an HTTP header X-Redirect-To giving the same URL that the
// link in the HTML indicates, allowing a non-browser user-agent to traverse
// this robotically in automated tests.
var Handler http.Handler

type handler struct{}

func (h handler) ServeHTTP(resp http.ResponseWriter, req *http.Request) {
	switch req.URL.Path {
	case "/authz":
		h.serveAuthz(resp, req)
	case "/token":
		h.serveToken(resp, req)
	case "/revoke":
		h.serveRevoke(resp, req)
	default:
		resp.WriteHeader(404)
	}
}

func (h handler) serveAuthz(resp http.ResponseWriter, req *http.Request) {
	args := req.URL.Query()
	if rt := args.Get("response_type"); rt != "code" {
		resp.WriteHeader(400)
		resp.Write([]byte("wrong response_type"))
		log.Printf("/authz: incorrect response type %q", rt)
		return
	}
	redirectURL, err := url.Parse(args.Get("redirect_uri"))
	if err != nil {
		resp.WriteHeader(400)
		resp.Write([]byte(fmt.Sprintf("invalid redirect_uri %s: %s", args.Get("redirect_uri"), err)))
		return
	}

	state := args.Get("state")
	challenge := args.Get("code_challenge")
	challengeMethod := args.Get("code_challenge_method")
	if challengeMethod == "" {
		challengeMethod = "plain"
	}

	// NOTE: This is not a suitable implementation for a real OAuth server
	// because the code challenge is providing no security whatsoever. This
	// is just a simple implementation for this stub server.
	code := fmt.Sprintf("%s:%s", challengeMethod, challenge)

	redirectQuery := redirectURL.Query()
	redirectQuery.Set("code", code)
	if state != "" {
		redirectQuery.Set("state", state)
	}
	redirectURL.RawQuery = redirectQuery.Encode()

	respBody := fmt.Sprintf(`<a href="%s">Log In and Consent</a>`, html.EscapeString(redirectURL.String()))
	resp.Header().Set("Content-Type", "text/html")
	resp.Header().Set("Content-Length", fmt.Sprintf("%d", len(respBody)))
	resp.Header().Set("X-Redirect-To", redirectURL.String()) // For robotic clients, using webbrowser.MockLauncher
	resp.WriteHeader(200)
	resp.Write([]byte(respBody))
}

func (h handler) serveToken(resp http.ResponseWriter, req *http.Request) {
	if req.Method != "POST" {
		resp.WriteHeader(405)
		log.Printf("/token: unsupported request method %q", req.Method)
		return
	}

	if err := req.ParseForm(); err != nil {
		resp.WriteHeader(500)
		log.Printf("/token: error parsing body: %s", err)
		return
	}

	grantType := req.Form.Get("grant_type")
	log.Printf("/token: grant_type is %q", grantType)
	switch grantType {

	case "authorization_code":
		code := req.Form.Get("code")
		codeParts := strings.SplitN(code, ":", 2)
		if len(codeParts) != 2 {
			log.Printf("/token: invalid code %q", code)
			resp.Header().Set("Content-Type", "application/json")
			resp.WriteHeader(400)
			resp.Write([]byte(`{"error":"invalid_grant"}`))
			return
		}

		codeVerifier := req.Form.Get("code_verifier")

		switch codeParts[0] {
		case "plain":
			if codeParts[1] != codeVerifier {
				log.Printf("/token: incorrect code verifier %q; want %q", codeParts[1], codeVerifier)
				resp.Header().Set("Content-Type", "application/json")
				resp.WriteHeader(400)
				resp.Write([]byte(`{"error":"invalid_grant"}`))
				return
			}
		case "S256":
			h := sha256.New()
			h.Write([]byte(codeVerifier))
			encVerifier := base64.RawURLEncoding.EncodeToString(h.Sum(nil))
			if codeParts[1] != encVerifier {
				log.Printf("/token: incorrect code verifier %q; want %q", codeParts[1], encVerifier)
				resp.Header().Set("Content-Type", "application/json")
				resp.WriteHeader(400)
				resp.Write([]byte(`{"error":"invalid_grant"}`))
				return
			}
		default:
			log.Printf("/token: unsupported challenge method %q", codeParts[0])
			resp.Header().Set("Content-Type", "application/json")
			resp.WriteHeader(400)
			resp.Write([]byte(`{"error":"invalid_grant"}`))
			return
		}

		resp.Header().Set("Content-Type", "application/json")
		resp.WriteHeader(200)
		resp.Write([]byte(`{"access_token":"good-token","token_type":"bearer"}`))
		log.Println("/token: successful request")

	case "password":
		username := req.Form.Get("username")
		password := req.Form.Get("password")

		if username == "wrong" || password == "wrong" {
			// These special "credentials" allow testing for the error case.
			resp.Header().Set("Content-Type", "application/json")
			resp.WriteHeader(400)
			resp.Write([]byte(`{"error":"invalid_grant"}`))
			log.Println("/token: 'wrong' credentials")
			return
		}

		resp.Header().Set("Content-Type", "application/json")
		resp.WriteHeader(200)
		resp.Write([]byte(`{"access_token":"good-token","token_type":"bearer"}`))
		log.Println("/token: successful request")

	default:
		resp.WriteHeader(400)
		log.Printf("/token: unsupported grant type %q", grantType)
	}
}

func (h handler) serveRevoke(resp http.ResponseWriter, req *http.Request) {
	resp.WriteHeader(404)
}

func init() {
	Handler = handler{}
}
