package lark

import (
	"encoding/json"
	"fmt"
	"io"
	"net/http"
	"strings"

	"github.com/gin-gonic/gin"
	"github.com/spf13/viper"

	"jiraport/pkg/log"
	"jiraport/pkg/queue"
)

type Lark struct {
	queue         chan<- queue.Event
	notifyAddress string
}

// create lark service and register route in gin router
func New(queue chan<- queue.Event, r *gin.RouterGroup) (*Lark, error) {
	notifyAddress := viper.GetString("notify-address")

	l := &Lark{queue: queue, notifyAddress: notifyAddress}

	r.POST("/ack", l.ackEventHandler())

	return l, nil
}

// send message to end server
func (lk *Lark) Notify(msgValues *Message) (*MessageIndex, error) {
	msg, err := json.Marshal(msgValues)
	if err != nil {
		return nil, err
	}

	resp, err := http.Post(lk.notifyAddress, "application/json", strings.NewReader(string(msg)))
	if err != nil {
		return nil, err
	}
	defer resp.Body.Close()
	body_raw, err := io.ReadAll(resp.Body)
	if err != nil {
		return nil, fmt.Errorf("error when read resp body, %w", err)
	}
	if resp.StatusCode/100 != 2 {
		return nil, fmt.Errorf("receive bad status code %d, body is %s", resp.StatusCode, string(body_raw))
	}
	var respBody struct {
		MessageIndex MessageIndex `json:"message_id"`
	}
	err = json.Unmarshal(body_raw, &respBody)
	if err != nil {
		return nil, fmt.Errorf("unmarshal body error, %w", err)
	}
	return &respBody.MessageIndex, nil
}

type AckWebhookEvent struct {
	MessageIndex MessageIndex `json:"message_id"`
}

// handle http post and send ack event to resolver
func (lk *Lark) ackEventHandler() func(*gin.Context) {
	return func(ctx *gin.Context) {
		var ack AckWebhookEvent
		err := ctx.ShouldBindJSON(&ack)
		if err != nil {
			log.Error("err", err)
			ctx.Status(http.StatusBadRequest)
			return
		}
		log.Debug("msg", "ack rev", "id", ack.MessageIndex)
		ev := queue.Event{Name: "NotificationAck", Payload: ack.MessageIndex}
		lk.queue <- ev

		ctx.Status(http.StatusOK)
	}
}
