package handlers

import (
	"context"
	"encoding/json"
	"fmt"
	"net/http"
	"net/url"
	"strings"
	"time"

	"github.com/gin-gonic/gin"

	"sproutgate-backend/internal/storage"
)

const turnstileVerifyURL = "https://challenges.cloudflare.com/turnstile/v0/siteverify"

type turnstileVerifyResp struct {
	Success bool `json:"success"`
}

// verifyTurnstileToken 向 Cloudflare 验证 Turnstile token，失败返回用户可见错误。
func verifyTurnstileToken(ctx context.Context, secretKey, token, remoteIP string) error {
	if strings.TrimSpace(token) == "" {
		return fmt.Errorf("请完成人机验证")
	}
	form := url.Values{}
	form.Set("secret", secretKey)
	form.Set("response", token)
	if remoteIP != "" {
		form.Set("remoteip", remoteIP)
	}
	client := &http.Client{Timeout: 8 * time.Second}
	resp, err := client.PostForm(turnstileVerifyURL, form)
	if err != nil {
		return fmt.Errorf("人机验证服务暂时不可用，请稍后重试")
	}
	defer resp.Body.Close()
	var result turnstileVerifyResp
	if err := json.NewDecoder(resp.Body).Decode(&result); err != nil {
		return fmt.Errorf("人机验证响应解析失败")
	}
	if !result.Success {
		return fmt.Errorf("人机验证未通过，请重试")
	}
	return nil
}

// GetAdminTurnstile
// @Summary Turnstile 配置（脱敏）
// @Tags admin
// @Produce json
// @Security AdminToken
// @Success 200 {object} map[string]interface{}
// @Failure 401 {object} map[string]interface{}
// @Router /api/admin/turnstile [get]
func (h *Handler) GetAdminTurnstile(c *gin.Context) {
	cfg := h.store.GetTurnstileConfig()
	c.JSON(http.StatusOK, gin.H{
		"enabled":      cfg.Enabled,
		"siteKey":      strings.TrimSpace(cfg.SiteKey),
		"secretKeySet": strings.TrimSpace(cfg.SecretKey) != "",
	})
}

// PutAdminTurnstile
// @Summary 更新 Turnstile 配置
// @Tags admin
// @Accept json
// @Produce json
// @Security AdminToken
// @Param body body PutAdminTurnstileRequest true "siteKey、secretKey"
// @Success 200 {object} map[string]interface{}
// @Failure 400 {object} map[string]interface{}
// @Failure 401 {object} map[string]interface{}
// @Failure 500 {object} map[string]interface{}
// @Router /api/admin/turnstile [put]
func (h *Handler) PutAdminTurnstile(c *gin.Context) {
	var req PutAdminTurnstileRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid request"})
		return
	}
	in := storage.TurnstileConfig{
		Enabled:   req.Enabled,
		SiteKey:   strings.TrimSpace(req.SiteKey),
		SecretKey: strings.TrimSpace(req.SecretKey),
	}
	if err := h.store.UpdateTurnstileConfig(in); err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to save turnstile config"})
		return
	}
	h.GetAdminTurnstile(c)
}
