package captcha

import (
	"encoding/json"
	"fmt"
	"io/ioutil"
	"net/http"
	"net/url"
	"strings"
	"time"
)

const (
	rootURL = "https://hcaptcha.com/siteverify"
)

type captchaResp struct {
	Success    bool     `json:"success"`
	ErrorCodes []string `json:"error_codes"`
}

// Captcha is a simple Captcha client.
// It currently implements hcaptcha.com
type Captcha struct {
	o      Opt
	client *http.Client
}

type Opt struct {
	CaptchaSecret string `json:"captcha_secret"`
}

// New returns a new instance of the HTTP CAPTCHA client.
func New(o Opt) *Captcha {
	timeout := time.Second * 5

	return &Captcha{
		o: o,
		client: &http.Client{
			Timeout: timeout,
			Transport: &http.Transport{
				MaxIdleConnsPerHost:   10,
				MaxConnsPerHost:       100,
				ResponseHeaderTimeout: timeout,
				IdleConnTimeout:       timeout,
			},
		}}
}

// Verify verifies a CAPTCHA request.
func (c *Captcha) Verify(token string) (error, bool) {
	resp, err := c.client.PostForm(rootURL, url.Values{
		"secret":   {c.o.CaptchaSecret},
		"response": {token},
	})
	if err != nil {
		return err, false
	}

	defer resp.Body.Close()
	body, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		return err, false
	}

	var r captchaResp
	if json.Unmarshal(body, &r); err != nil {
		return err, true
	}

	if r.Success != true {
		return fmt.Errorf("captcha failed: %s", strings.Join(r.ErrorCodes, ",")), false
	}

	return nil, true
}
