package handlers

import (
	"bytes"
	"code-review/config"
	"code-review/services"
	"code-review/services/platforms"
	"crypto/hmac"
	"crypto/sha256"
	"encoding/hex"
	"fmt"
	"io/ioutil"
	"log"

	"github.com/gin-gonic/gin"
)

type WebhookHandler struct {
	reviewService *services.ReviewService
}

func NewWebhookHandler(reviewService *services.ReviewService) *WebhookHandler {
	return &WebhookHandler{
		reviewService: reviewService,
	}
}

func (h *WebhookHandler) HandleWebhook(c *gin.Context) {
	platform := c.Param("platform")
	log.Printf("收到 webhook 请求: platform=%s", platform)

	// 验证 webhook 签名
	if !h.verifySignature(c, platform) {
		log.Printf("webhook 签名验证失败: platform=%s", platform)
		c.JSON(400, gin.H{"error": "无效的签名"})
		return
	}

	// 解析请求体
	event, err := h.parseWebhookEvent(c, platform)
	if err != nil {
		log.Printf("解析 webhook 事件失败: platform=%s, error=%v", platform, err)
		c.JSON(400, gin.H{"error": err.Error()})
		return
	}

	// 启动代码审查
	if err := h.reviewService.Review(event); err != nil {
		log.Printf("代码审查失败: platform=%s, error=%v", platform, err)
		c.JSON(500, gin.H{"error": err.Error()})
		return
	}

	log.Printf("代码审查完成: platform=%s", platform)
	c.JSON(200, gin.H{"message": "success"})
}

func (h *WebhookHandler) verifySignature(c *gin.Context, platform string) bool {
	body, err := c.GetRawData()
	if err != nil {
		return false
	}
	c.Request.Body = ioutil.NopCloser(bytes.NewBuffer(body))

	cfg := config.GetConfig()
	// 查找对应的平台配置
	var gitConfig config.GitConfig
	found := false
	for _, p := range cfg.Git {
		if p.Name == platform {
			gitConfig = p
			found = true
			break
		}
	}
	if !found {
		return false
	}

	// 获取签名
	signature := c.GetHeader(gitConfig.SignatureHeader)
	if signature == "" {
		return false
	}

	mac := hmac.New(sha256.New, []byte(gitConfig.Secret))
	mac.Write(body)
	expectedMAC := hex.EncodeToString(mac.Sum(nil))

	return hmac.Equal([]byte(signature), []byte(expectedMAC)) || hmac.Equal([]byte(signature), []byte(gitConfig.Secret))
}

func (h *WebhookHandler) parseWebhookEvent(c *gin.Context, platform string) (services.WebhookEvent, error) {
	cfg := config.GetConfig()
	// 查找对应的平台配置
	var platformConfig config.GitConfig
	found := false
	for _, p := range cfg.Git {
		if p.Name == platform {
			platformConfig = p
			found = true
			break
		}
	}
	if !found {
		return nil, fmt.Errorf("不支持的平台: %s", platform)
	}

	// 获取事件类型
	eventType := c.GetHeader(platformConfig.EventHeader)
	if eventType == "" {
		return nil, fmt.Errorf("未找到事件类型 header: %s", platformConfig.EventHeader)
	}

	var event services.WebhookEvent
	switch platformConfig.Type {
	case "gogs":
		event = platforms.NewGogsEvent(
			platformConfig.APIBase,
			platformConfig.Token,
			eventType,
		)
	case "gitea":
		event = platforms.NewGiteaEvent(
			platformConfig.APIBase,
			platformConfig.Token,
			eventType,
		)
	//case "gitee":
	//	event = &platforms.GiteeEvent{
	//		ApiBase: platformConfig.APIBase,
	//		Token:   platformConfig.Token,
	//	}
	case "gitlab":
		event = platforms.NewGitlabEvent(
			platformConfig.APIBase,
			platformConfig.Token,
			eventType,
		)
	default:
		return nil, fmt.Errorf("不支持的平台: %s", platform)
	}

	// 只处理 push 和 pull_request 事件
	//if eventType != "push" && eventType != "pull_request" {
	//	return nil, fmt.Errorf("不支持的事件类型: %s", eventType)
	//}

	if err := c.ShouldBindJSON(event); err != nil {
		return nil, err
	}

	return event, nil
}