package notifications

import (
	gmessaging "github.com/tech/sendico/pkg/generated/gmessaging"
	"github.com/tech/sendico/pkg/merrors"
	messaging "github.com/tech/sendico/pkg/messaging/envelope"
	"github.com/tech/sendico/pkg/model"
	nm "github.com/tech/sendico/pkg/model/notification"
	"github.com/tech/sendico/pkg/mservice"
	"google.golang.org/protobuf/proto"
)

type SiteRequestNotification struct {
	messaging.Envelope
	requestType    gmessaging.SiteRequestEvent_RequestType
	demoRequest    *model.DemoRequest
	contactRequest *model.ContactRequest
	callRequest    *model.CallRequest
}

func (srn *SiteRequestNotification) Serialize() ([]byte, error) {
	msg := gmessaging.SiteRequestEvent{
		Type: srn.requestType,
	}

	switch srn.requestType {
	case gmessaging.SiteRequestEvent_REQUEST_TYPE_DEMO:
		if srn.demoRequest == nil {
			return nil, merrors.InvalidArgument("demo request payload is empty", "request")
		}
		msg.Payload = &gmessaging.SiteRequestEvent_Demo{
			Demo: &gmessaging.SiteDemoRequest{
				Name:             srn.demoRequest.Name,
				OrganizationName: srn.demoRequest.OrganizationName,
				Phone:            srn.demoRequest.Phone,
				WorkEmail:        srn.demoRequest.WorkEmail,
				PayoutVolume:     srn.demoRequest.PayoutVolume,
				Comment:          srn.demoRequest.Comment,
			},
		}
	case gmessaging.SiteRequestEvent_REQUEST_TYPE_CONTACT:
		if srn.contactRequest == nil {
			return nil, merrors.InvalidArgument("contact request payload is empty", "request")
		}
		msg.Payload = &gmessaging.SiteRequestEvent_Contact{
			Contact: &gmessaging.SiteContactRequest{
				Name:    srn.contactRequest.Name,
				Email:   srn.contactRequest.Email,
				Phone:   srn.contactRequest.Phone,
				Company: srn.contactRequest.Company,
				Topic:   srn.contactRequest.Topic,
				Message: srn.contactRequest.Message,
			},
		}
	case gmessaging.SiteRequestEvent_REQUEST_TYPE_CALL:
		if srn.callRequest == nil {
			return nil, merrors.InvalidArgument("call request payload is empty", "request")
		}
		msg.Payload = &gmessaging.SiteRequestEvent_Call{
			Call: &gmessaging.SiteCallRequest{
				Name:          srn.callRequest.Name,
				Phone:         srn.callRequest.Phone,
				Email:         srn.callRequest.Email,
				Company:       srn.callRequest.Company,
				PreferredTime: srn.callRequest.PreferredTime,
				Message:       srn.callRequest.Message,
			},
		}
	default:
		return nil, merrors.InvalidArgument("unsupported site request type", "type")
	}

	data, err := proto.Marshal(&msg)
	if err != nil {
		return nil, err
	}
	return srn.Wrap(data)
}

func newSiteRequestEvent() model.NotificationEvent {
	return model.NewNotification(mservice.Site, nm.NACreated)
}

func NewDemoRequestEvent() model.NotificationEvent {
	return newSiteRequestEvent()
}

func NewContactRequestEvent() model.NotificationEvent {
	return newSiteRequestEvent()
}

func NewCallRequestEvent() model.NotificationEvent {
	return newSiteRequestEvent()
}

func NewDemoRequestEnvelope(sender string, request *model.DemoRequest) messaging.Envelope {
	return &SiteRequestNotification{
		Envelope:       messaging.CreateEnvelope(sender, newSiteRequestEvent()),
		requestType:    gmessaging.SiteRequestEvent_REQUEST_TYPE_DEMO,
		demoRequest:    request,
		contactRequest: nil,
		callRequest:    nil,
	}
}

func NewContactRequestEnvelope(sender string, request *model.ContactRequest) messaging.Envelope {
	return &SiteRequestNotification{
		Envelope:       messaging.CreateEnvelope(sender, newSiteRequestEvent()),
		requestType:    gmessaging.SiteRequestEvent_REQUEST_TYPE_CONTACT,
		contactRequest: request,
		demoRequest:    nil,
		callRequest:    nil,
	}
}

func NewCallRequestEnvelope(sender string, request *model.CallRequest) messaging.Envelope {
	return &SiteRequestNotification{
		Envelope:       messaging.CreateEnvelope(sender, newSiteRequestEvent()),
		requestType:    gmessaging.SiteRequestEvent_REQUEST_TYPE_CALL,
		callRequest:    request,
		demoRequest:    nil,
		contactRequest: nil,
	}
}
