package notifications

import (
	"context"

	gmessaging "github.com/tech/sendico/pkg/generated/gmessaging"
	me "github.com/tech/sendico/pkg/messaging/envelope"
	internalsite "github.com/tech/sendico/pkg/messaging/internal/notifications/site"
	np "github.com/tech/sendico/pkg/messaging/notifications/processor"
	handler "github.com/tech/sendico/pkg/messaging/notifications/site/handler"
	"github.com/tech/sendico/pkg/mlogger"
	"github.com/tech/sendico/pkg/model"
	"go.uber.org/zap"
	"google.golang.org/protobuf/proto"
)

type SiteRequestProcessor struct {
	logger         mlogger.Logger
	demoHandler    handler.DemoRequestHandler
	contactHandler handler.ContactRequestHandler
	callHandler    handler.CallRequestHandler
	event          model.NotificationEvent
}

func (srp *SiteRequestProcessor) Process(ctx context.Context, envelope me.Envelope) error {
	var msg gmessaging.SiteRequestEvent
	if err := proto.Unmarshal(envelope.GetData(), &msg); err != nil {
		srp.logger.Warn("Failed to decode site request envelope", zap.Error(err), zap.String("topic", srp.event.ToString()))
		return err
	}

	switch msg.GetType() {
	case gmessaging.SiteRequestEvent_REQUEST_TYPE_DEMO:
		if srp.demoHandler == nil {
			srp.logger.Warn("Demo request handler is not configured")
			return nil
		}
		demo := msg.GetDemo()
		if demo == nil {
			srp.logger.Warn("Demo request payload is empty")
			return nil
		}
		request := &model.DemoRequest{
			Name:             demo.GetName(),
			OrganizationName: demo.GetOrganizationName(),
			Phone:            demo.GetPhone(),
			WorkEmail:        demo.GetWorkEmail(),
			PayoutVolume:     demo.GetPayoutVolume(),
			Comment:          demo.GetComment(),
		}
		return srp.demoHandler(ctx, request)
	case gmessaging.SiteRequestEvent_REQUEST_TYPE_CONTACT:
		if srp.contactHandler == nil {
			srp.logger.Warn("Contact request handler is not configured")
			return nil
		}
		contact := msg.GetContact()
		if contact == nil {
			srp.logger.Warn("Contact request payload is empty")
			return nil
		}
		request := &model.ContactRequest{
			Name:    contact.GetName(),
			Email:   contact.GetEmail(),
			Phone:   contact.GetPhone(),
			Company: contact.GetCompany(),
			Topic:   contact.GetTopic(),
			Message: contact.GetMessage(),
		}
		return srp.contactHandler(ctx, request)
	case gmessaging.SiteRequestEvent_REQUEST_TYPE_CALL:
		if srp.callHandler == nil {
			srp.logger.Warn("Call request handler is not configured")
			return nil
		}
		call := msg.GetCall()
		if call == nil {
			srp.logger.Warn("Call request payload is empty")
			return nil
		}
		request := &model.CallRequest{
			Name:          call.GetName(),
			Phone:         call.GetPhone(),
			Email:         call.GetEmail(),
			Company:       call.GetCompany(),
			PreferredTime: call.GetPreferredTime(),
			Message:       call.GetMessage(),
		}
		return srp.callHandler(ctx, request)
	default:
		srp.logger.Warn("Received site request with unsupported type", zap.Any("type", msg.GetType()))
		return nil
	}
}

func (srp *SiteRequestProcessor) GetSubject() model.NotificationEvent {
	return srp.event
}

func NewSiteRequestProcessor(logger mlogger.Logger, demo handler.DemoRequestHandler, contact handler.ContactRequestHandler, call handler.CallRequestHandler) np.EnvelopeProcessor {
	return &SiteRequestProcessor{
		logger:         logger.Named("site_request_processor"),
		demoHandler:    demo,
		contactHandler: contact,
		callHandler:    call,
		event:          internalsite.NewDemoRequestEvent(),
	}
}
