package antispam

import (
	"net/http"
	"net/http/httptest"
	"net/url"
	"strings"
	"testing"
)

func setupHcaptchaTest(t *testing.T) (*httptest.Server, *HCaptcha) {
	server := httptest.NewServer(http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
		if r.Method != http.MethodPost || r.URL.Path != "/siteverify" {
			t.Errorf("Expecting call to `POST /siteverify`, got: %s %s", r.Method, r.URL.Path)
		}

		err := r.ParseForm()
		if err != nil {
			t.Errorf("Form parsing error: %s", err)
		}
		if secret := r.PostForm.Get("secret"); secret != "test" {
			t.Errorf("Expecting hCaptcha secret key `test`, got: %s", secret)
		}

		w.Header().Set("Content-Type", "application/json")
		w.WriteHeader(http.StatusOK)

		if r.PostForm.Get("response") == "test" {
			_, _ = w.Write([]byte(`{"success": true, "hostname": "localhost"}`))
		} else {
			_, _ = w.Write([]byte(`{"success": false, "hostname": "localhost", "error-codes": ["invalid-input-response"]}`))
		}
	}))
	hcaptcha := newHcaptcha("test", "test", server.URL)
	return server, hcaptcha
}

// TestHcaptchaEmpty checks that empty requests (without the hCaptcha token) are blocked.
func TestHcaptchaEmpty(t *testing.T) {
	server, hcaptcha := setupHcaptchaTest(t)
	defer server.Close()

	req := httptest.NewRequest(http.MethodPost, "http://localhost/form", nil)
	result, err := hcaptcha.CheckRequest(req)
	if result || err != nil {
		t.Errorf("hcaptcha.CheckRequest(req) = %v, %v, expecting false, nil", result, err)
	}
}

// TestHcaptchaBadToken checks that invalid hCaptcha tokens are blocked.
func TestHcaptchaBadToken(t *testing.T) {
	server, hcaptcha := setupHcaptchaTest(t)
	defer server.Close()

	form := url.Values{}
	form.Add("x-captcha-response", "wrong")
	req := httptest.NewRequest(http.MethodPost, "http://localhost/form", strings.NewReader(form.Encode()))
	req.Header.Set("Content-Type", "application/x-www-form-urlencoded")

	result, err := hcaptcha.CheckRequest(req)
	if result || err != nil {
		t.Errorf("hcaptcha.CheckRequest(req) = %v, %v, want false, nil", result, err)
	}
}

// TestHcaptchaSuccess mocks a successful hCaptcha verification run.
func TestHcaptchaSuccess(t *testing.T) {
	server, hcaptcha := setupHcaptchaTest(t)
	defer server.Close()

	form := url.Values{}
	form.Add("x-captcha-response", "test")
	req := httptest.NewRequest(http.MethodPost, "http://localhost/form", strings.NewReader(form.Encode()))
	req.Header.Set("Content-Type", "application/x-www-form-urlencoded")

	result, err := hcaptcha.CheckRequest(req)
	if !result || err != nil {
		t.Errorf("hcaptcha.CheckRequest(req) = %v, %v, want true, nil", result, err)
	}
}
