package notifications

import (
	"context"

	"github.com/tech/sendico/pkg/db/account"
	gmessaging "github.com/tech/sendico/pkg/generated/gmessaging"
	me "github.com/tech/sendico/pkg/messaging/envelope"
	mah "github.com/tech/sendico/pkg/messaging/notifications/account/handler"
	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"
	"go.mongodb.org/mongo-driver/v2/bson"
	"go.uber.org/zap"
	"google.golang.org/protobuf/proto"
)

type PasswordResetNotificationProcessor struct {
	logger  mlogger.Logger
	handler mah.PasswordResetHandler
	db      account.DB
	event   model.NotificationEvent
}

func (prnp *PasswordResetNotificationProcessor) Process(ctx context.Context, envelope me.Envelope) error {
	var msg gmessaging.PasswordResetEvent
	if err := proto.Unmarshal(envelope.GetData(), &msg); err != nil {
		prnp.logger.Warn("Failed to unmarshall envelope", zap.Error(err), zap.String("topic", prnp.event.ToString()))
		return err
	}
	accountRef, err := bson.ObjectIDFromHex(msg.AccountRef)
	if err != nil {
		prnp.logger.Warn("Failed to restore object ID", zap.Error(err), zap.String("topic", prnp.event.ToString()), zap.String("account_ref", msg.AccountRef))
		return err
	}
	var account model.Account
	if err := prnp.db.Get(ctx, accountRef, &account); err != nil {
		prnp.logger.Warn("Failed to fetch account", zap.Error(err), zap.String("topic", prnp.event.ToString()), zap.String("account_ref", msg.AccountRef))
		return err
	}
	return prnp.handler(ctx, &account, msg.ResetToken)
}

func (prnp *PasswordResetNotificationProcessor) GetSubject() model.NotificationEvent {
	return prnp.event
}

func NewPasswordResetMessageProcessor(logger mlogger.Logger, handler mah.PasswordResetHandler, db account.DB, action nm.NotificationAction) np.EnvelopeProcessor {
	event := NewPasswordResetNotification(action)
	return &PasswordResetNotificationProcessor{
		logger:  logger.Named("password_reset_processor"),
		handler: handler,
		db:      db,
		event:   event,
	}
}
