package ack

import (
	"context"
	"encoding/json"
	"log/slog"

	"github.com/tidbcloud/jiraport/pkg/api/lark"
	"github.com/tidbcloud/jiraport/pkg/clients/jira"
	"github.com/tidbcloud/jiraport/pkg/clients/lambda"
	"github.com/tidbcloud/jiraport/pkg/config"
	"github.com/tidbcloud/jiraport/pkg/db"
	"github.com/tidbcloud/jiraport/pkg/entity"
	ntf "github.com/tidbcloud/jiraport/pkg/resolver/notification"
)

type AckEventHandler struct {
	logger          *slog.Logger
	dbClient        db.Interface
	notificationSvc *ntf.Notifications
	jiraClient      jira.Interface
}

func New(
	logger *slog.Logger,
	dbClient db.Interface,
	ns *ntf.Notifications,
	jira jira.Interface,
) (*AckEventHandler, error) {
	return &AckEventHandler{
		logger:          logger,
		dbClient:        dbClient,
		notificationSvc: ns,
		jiraClient:      jira,
	}, nil
}

func (handler *AckEventHandler) Handle(ctx context.Context, ev lambda.Event) {
	var actEvent lark.AckWebhookEvent
	err := json.Unmarshal(ev.Payload, &actEvent)
	if err != nil {
		handler.logger.Error("decode ack event failed", "err", err, "payload", ev.Payload)
		return
	}

	handler.logger.Info("receive ack event", "msgIndex", actEvent.MessageIndex)
	msgIndex := entity.MessageIndex(actEvent.MessageIndex)
	msg, err := handler.dbClient.GetMessage(&msgIndex)
	if err != nil {
		handler.logger.Error("get message error", "err", err, "msgIndex", msgIndex)
		return
	}

	notification, err := handler.dbClient.GetNotification(msg.NotificationID)
	if err != nil {
		handler.logger.Error("get notification error",
			"err", err,
			"msgIndex", msgIndex,
			"notification_id", msg.NotificationID)
		return
	}

	err = handler.notificationSvc.Transition(msg.NotificationID, config.AcknowledgeEvent)
	err = ntf.HandleTransitionError(err, func(te *db.TransitionError) error {
		handler.logger.Warn("do transition error", "err", te, "msgIndex", msgIndex)
		return nil
	})
	if err != nil {
		handler.logger.Error("do transition error", "err", err, "msgIndex", msgIndex)
		return
	}

	_ = handler.jiraClient.AddComment(notification.IssueKey, "Response(not ack for Critical alert) in lark: "+string(msgIndex))
	handler.logger.Info("handle ack event success", "msgIndex", msgIndex)
}
