package notification

import (
	"context"
	"fmt"
)

// SDK provides a high-level interface for the notification service
type SDK struct {
	service NotificationService
	config  *Config
}

// NewSDK creates a new notification SDK with the provided configuration and logger
func New(config *Config, logger Logger) (*SDK, error) {
	if config == nil {
		config = DefaultConfig()
	}

	client, err := NewClient(config, logger)
	if err != nil {
		return nil, fmt.Errorf("failed to create notification client: %w", err)
	}

	service := NewService(client)

	return &SDK{
		service: service,
		config:  config,
	}, nil
}

// NewSDKWithClient creates a new notification SDK with a custom HTTP client
func NewSDKWithClient(config *Config, httpClient HTTPClient, logger Logger) (*SDK, error) {
	if config == nil {
		config = DefaultConfig()
	}

	client, err := NewClientWithHTTPClient(config, httpClient, logger)
	if err != nil {
		return nil, fmt.Errorf("failed to create notification client: %w", err)
	}

	service := NewService(client)

	return &SDK{
		service: service,
		config:  config,
	}, nil
}

// SendNotification sends a custom notification request
func (s *SDK) SendNotification(ctx context.Context, req *NotificationRequest) (*NotificationResponse, error) {
	return s.service.SendNotification(ctx, req)
}

// SendEmail sends an email notification
func (s *SDK) SendEmail(ctx context.Context, model Model) (*NotificationResponse, error) {
	return s.service.SendEmail(ctx, model)
}

// SendSMS sends an SMS notification
func (s *SDK) SendSMS(ctx context.Context, model Model) (*NotificationResponse, error) {
	return s.service.SendSMS(ctx, model)
}

// SendPush sends a push notification
func (s *SDK) SendPush(ctx context.Context, model Model) (*NotificationResponse, error) {
	return s.service.SendPush(ctx, model)
}

// SendOTP sends an OTP notification
func (s *SDK) SendOTP(ctx context.Context, model Model) (*NotificationResponse, error) {
	return s.service.SendOTP(ctx, model)
}

// GetNotifications retrieves a list of notifications from the notification service
func (s *SDK) GetNotifications(ctx context.Context, req *GetNotificationsRequest) (*NotificationListResponse, error) {
	return s.service.GetNotifications(ctx, req)
}

// GetNotification retrieves a single notification by ID
func (s *SDK) GetNotification(ctx context.Context, notificationID string) (*DetailedNotificationResponse, error) {
	return s.service.GetNotification(ctx, notificationID)
}

// MarkSeen marks a notification as seen
func (s *SDK) MarkSeen(ctx context.Context, notificationID string) (*MarkSeenResponse, error) {
	return s.service.MarkSeen(ctx, notificationID)
}

// AllMarkSeen marks all notifications as seen for a user
func (s *SDK) AllMarkSeen(ctx context.Context, userID string) (*MarkSeenResponse, error) {
	return s.service.AllMarkSeen(ctx, userID)
}

// NewBuilder creates a new notification builder for fluent API usage
func (s *SDK) NewBuilder() Builder {
	return s.service.(*Service).NewBuilder()
}

// Health checks if the notification service is available
func (s *SDK) Health(ctx context.Context) error {
	return s.service.Health(ctx)
}

// GetConfig returns the current configuration
func (s *SDK) GetConfig() *Config {
	return s.config
}

// Convenience functions for quick notifications

// QuickEmail sends a simple email notification
func (s *SDK) QuickEmail(ctx context.Context, model Model) error {
	_, err := s.SendEmail(ctx, model)
	return err
}

// QuickSMS sends a simple SMS notification
func (s *SDK) QuickSMS(ctx context.Context, model Model) error {
	_, err := s.SendSMS(ctx, model)
	return err
}

// QuickPush sends a simple push notification
func (s *SDK) QuickPush(ctx context.Context, model Model) error {
	_, err := s.SendPush(ctx, model)
	return err
}

// QuickOTP sends a simple OTP notification
func (s *SDK) QuickOTP(ctx context.Context, model Model) error {
	_, err := s.SendOTP(ctx, model)
	return err
}

// QuickGetNotifications retrieves notifications with simple parameters
func (s *SDK) QuickGetNotifications(ctx context.Context, userID, status string) (*NotificationListResponse, error) {
	req := &GetNotificationsRequest{
		UserID: userID,
		Status: status,
	}
	return s.GetNotifications(ctx, req)
}

// GetNotificationsByUser retrieves notifications for a specific user
func (s *SDK) GetNotificationsByUser(ctx context.Context, userID string, page, perPage int) (*NotificationListResponse, error) {
	req := &GetNotificationsRequest{
		UserID:  userID,
		Page:    page,
		PerPage: perPage,
	}
	return s.GetNotifications(ctx, req)
}

// GetNotificationsByStatus retrieves notifications by status
func (s *SDK) GetNotificationsByStatus(ctx context.Context, status string, page, perPage int) (*NotificationListResponse, error) {
	req := &GetNotificationsRequest{
		Status:  status,
		Page:    page,
		PerPage: perPage,
	}
	return s.GetNotifications(ctx, req)
}

// QuickMarkSeen marks a notification as seen (convenience method)
func (s *SDK) QuickMarkSeen(ctx context.Context, notificationID string) error {
	_, err := s.MarkSeen(ctx, notificationID)
	return err
}

// Batch operations for sending multiple notifications

// BatchRequest represents a batch notification request
type BatchRequest struct {
	Requests []*NotificationRequest `json:"requests"`
}

// BatchResponse represents the response from batch operations
type BatchResponse struct {
	Responses []BatchItemResponse `json:"responses"`
	Success   int                 `json:"success"`
	Failed    int                 `json:"failed"`
}

// BatchItemResponse represents individual response in batch
type BatchItemResponse struct {
	Index    int                   `json:"index"`
	Success  bool                  `json:"success"`
	Response *NotificationResponse `json:"response,omitempty"`
	Error    string                `json:"error,omitempty"`
}

// SendBatch sends multiple notifications in batch (sequential for now)
func (s *SDK) SendBatch(ctx context.Context, requests []*NotificationRequest) (*BatchResponse, error) {
	if len(requests) == 0 {
		return &BatchResponse{
			Responses: []BatchItemResponse{},
			Success:   0,
			Failed:    0,
		}, nil
	}

	responses := make([]BatchItemResponse, len(requests))
	successCount := 0
	failedCount := 0

	for i, req := range requests {
		resp, err := s.service.SendNotification(ctx, req)
		if err != nil {
			responses[i] = BatchItemResponse{
				Index:   i,
				Success: false,
				Error:   err.Error(),
			}
			failedCount++
		} else {
			responses[i] = BatchItemResponse{
				Index:    i,
				Success:  true,
				Response: resp,
			}
			successCount++
		}
	}

	return &BatchResponse{
		Responses: responses,
		Success:   successCount,
		Failed:    failedCount,
	}, nil
}
