package webhook

import (
	"context"
	"encoding/json"
	"fmt"

	"github.com/go-logr/logr"
	larkevent "github.com/larksuite/oapi-sdk-go/v3/event"
	larkim "github.com/larksuite/oapi-sdk-go/v3/service/im/v1"
)

type LarkEventDispatcher struct {
	logger            logr.Logger
	eventType2Handler map[string][]larkevent.EventHandler
}

func (d *LarkEventDispatcher) OnMessageReceive(handler func(ctx context.Context, event *larkim.P2MessageReceiveV1) error) *LarkEventDispatcher {
	typ := "im.message.receive_v1"

	d.eventType2Handler[typ] = append(d.eventType2Handler[typ], larkim.NewP2MessageReceiveV1Handler(handler))
	return d
}

func (d *LarkEventDispatcher) Dispatch(ctx context.Context, body *larkevent.EventV2Body) error {
	handlers, ok := d.eventType2Handler[body.Header.EventType]
	if !ok {
		return nil
	}

	if len(handlers) == 0 {
		return nil
	}

	bodyJSON, err := json.Marshal(body)
	if err != nil {
		return fmt.Errorf("marshal event failed: %s", err)
	}

	event := handlers[0].Event()
	if err := json.Unmarshal(bodyJSON, event); err != nil {
		return fmt.Errorf("unmarshal event failed: %s", err)
	}

	for _, handler := range handlers {
		go func() {
			err = handler.Handle(context.WithoutCancel(ctx), event)
			if err != nil {
				d.logger.Error(err, "handle lark event failed", "event", event)
			}
		}()
	}

	return nil
}
