package notifications

import (
	"context"

	"github.com/tech/sendico/pkg/db/account"
	"github.com/tech/sendico/pkg/db/invitation"
	mih "github.com/tech/sendico/pkg/messaging/notifications/invitation/handler"
	no "github.com/tech/sendico/pkg/messaging/notifications/object"
	np "github.com/tech/sendico/pkg/messaging/notifications/processor"
	"github.com/tech/sendico/pkg/mlogger"
	"github.com/tech/sendico/pkg/model"
	nm "github.com/tech/sendico/pkg/model/notification"
	"github.com/tech/sendico/pkg/mservice"
	"github.com/tech/sendico/pkg/mutil/mzap"
	"go.mongodb.org/mongo-driver/v2/bson"
	"go.uber.org/zap"
)

type InvitationNotificaionProcessor struct {
	np.EnvelopeProcessor
	logger  mlogger.Logger
	handler mih.InvitationHandler
	db      invitation.DB
	adb     account.DB
}

func (ianp *InvitationNotificaionProcessor) onInvitation(
	ctx context.Context,
	objectType mservice.Type,
	objectRef, actorAccountRef bson.ObjectID,
	action nm.NotificationAction,
) error {
	var invitation model.Invitation
	if err := ianp.db.Unprotected().Get(ctx, objectRef, &invitation); err != nil {
		ianp.logger.Warn("Failed to fetch invitation object", zap.Error(err), mzap.ObjRef("object_ref", objectRef))
		return err
	}
	var account model.Account
	if err := ianp.adb.Get(ctx, actorAccountRef, &account); err != nil {
		ianp.logger.Warn("Failed to fetch actor account", zap.Error(err), mzap.ObjRef("actor_account_ref", actorAccountRef))
		return err
	}
	return ianp.handler(ctx, &account, &invitation)
}

func NewInvitationMessageProcessor(
	logger mlogger.Logger,
	handler mih.InvitationHandler,
	db invitation.DB,
	adb account.DB,
	action nm.NotificationAction,
) np.EnvelopeProcessor {
	l := logger.Named(mservice.Invitations)
	res := &InvitationNotificaionProcessor{
		logger:  l,
		db:      db,
		adb:     adb,
		handler: handler,
	}
	res.EnvelopeProcessor = no.NewObjectChangedMessageProcessor(l, mservice.Invitations, action, res.onInvitation)
	return res
}
