package hooks

import (
	"crypto/hmac"
	"crypto/sha256"
	"encoding/hex"
	"encoding/json"
	"io"
	"log/slog"
	"net/http"

	"github.com/gin-gonic/gin"
	"github.com/tidbcloud/jiraport/pkg/clients/lambda"
)

type Hook struct {
	logger       *slog.Logger
	lambdaClient lambda.Interface
	secret       string
}

// create hook service and register route in gin router
func New(
	r *gin.RouterGroup,
	logger *slog.Logger,
	lambdaClient lambda.Interface,
	secret string,
) (*Hook, error) {
	l := &Hook{
		logger:       logger,
		lambdaClient: lambdaClient,
		secret:       secret,
	}

	r.POST("/comment", l.hookEventHandler)
	return l, nil
}

// handle http post and send ack event to resolver
func (lk *Hook) hookEventHandler(ctx *gin.Context) {
	payload, err := io.ReadAll(ctx.Request.Body)
	if err != nil {
		ctx.JSON(400, gin.H{
			"message": "Failed to read payload",
		})
		return
	}
	provided := ctx.GetHeader("X-Hub-Signature")
	h := hmac.New(sha256.New, []byte(lk.secret))
	h.Write(payload)
	hash := hex.EncodeToString(h.Sum(nil))
	if provided != "sha256="+hash {
		ctx.JSON(http.StatusUnauthorized, gin.H{"error": "Unauthorized"})
		ctx.Abort()
		return
	}

	var hookBody HookBody
	err = json.Unmarshal(payload, &hookBody)
	if err != nil {
		lk.logger.Error("json unmarshal error",
			"err", err,
			"message_id", hookBody.JiraIssueID)
		ctx.Status(http.StatusBadRequest)
		return
	}
	ev := lambda.Event{
		Name:    "HookEvent",
		Payload: payload,
	}
	if err := lk.lambdaClient.InvokeAsync(ctx, ev); err != nil {
		lk.logger.Error("invoke lambda error",
			"err", err,
			"message_id", hookBody.JiraIssueID,
			"lambdaEvent", ev)
		ctx.Status(http.StatusInternalServerError)
		return
	}
	ctx.Status(http.StatusOK)
}
