package notification

import (
	"github.com/asaskevich/govalidator"
)

// EventType represents the type of notification event
type EventType string

const (
	EventTypeEmail EventType = "EMAIL"
	EventTypeSMS   EventType = "SMS"
	EventTypePush  EventType = "PUSH"
	EventTypeOTP   EventType = "OTP"
)

// NotificationMethods contains different delivery methods for notifications
type NotificationMethods struct {
	OTP   string `json:"otp,omitempty" valid:"optional"`
	SMS   string `json:"sms,omitempty" valid:"optional"`
	Push  string `json:"push,omitempty" valid:"optional"`
	Email string `json:"email,omitempty" valid:"optional,email"`
}

// NotificationRequest represents the request structure for sending notifications
type NotificationRequest struct {
	EventType EventType           `json:"event_type" valid:"required,in(EMAIL|SMS|PUSH|OTP)"`
	Message   string              `json:"message" valid:"required,length(1|1000)"`
	Methods   NotificationMethods `json:"methods" valid:"required"`
	UserID    string              `json:"user_id,omitempty" valid:"optional"`
}

// NotificationResponse represents the successful response from notification service
type NotificationResponse struct {
	Status string `json:"status"`
}

// NotificationErrorResponse represents the error response from notification service
type NotificationErrorResponse struct {
	Error string `json:"error"`
}

// Validate validates the notification request
func (nr *NotificationRequest) Validate() error {
	// First run govalidator validation
	if _, err := govalidator.ValidateStruct(nr); err != nil {
		return ErrValidation{Field: "struct", Message: err.Error()}
	}

	// Custom validation: ensure at least one method is provided based on event type
	switch nr.EventType {
	case EventTypeEmail:
		if nr.Methods.Email == "" {
			return ErrValidation{Field: "methods.email", Message: "email address is required for EMAIL event type"}
		}
	case EventTypeSMS:
		if nr.Methods.SMS == "" {
			return ErrValidation{Field: "methods.sms", Message: "SMS number is required for SMS event type"}
		}
	case EventTypePush:
		if nr.Methods.Push == "" {
			return ErrValidation{Field: "methods.push", Message: "push device token is required for PUSH event type"}
		}
	case EventTypeOTP:
		if nr.Methods.OTP == "" {
			return ErrValidation{Field: "methods.otp", Message: "OTP number is required for OTP event type"}
		}
	}

	return nil
}

// HasMethod checks if a specific method is configured
func (nm *NotificationMethods) HasMethod(eventType EventType) bool {
	switch eventType {
	case EventTypeEmail:
		return nm.Email != ""
	case EventTypeSMS:
		return nm.SMS != ""
	case EventTypePush:
		return nm.Push != ""
	case EventTypeOTP:
		return nm.OTP != ""
	default:
		return false
	}
}

// GetMethodValue returns the value for a specific method
func (nm *NotificationMethods) GetMethodValue(eventType EventType) string {
	switch eventType {
	case EventTypeEmail:
		return nm.Email
	case EventTypeSMS:
		return nm.SMS
	case EventTypePush:
		return nm.Push
	case EventTypeOTP:
		return nm.OTP
	default:
		return ""
	}
}
