package handlers

import (
	"net/http"

	apperrors "veza-backend-api/internal/errors"
	"veza-backend-api/internal/services"

	"github.com/gin-gonic/gin"
	"github.com/google/uuid"
)

var NotificationHandlersInstance *NotificationHandlers

// NotificationServiceInterface defines the interface for notification operations
// This allows for easier testing with mocks
type NotificationServiceInterface interface {
	GetNotifications(userID uuid.UUID, unreadOnly bool) ([]services.Notification, error)
	MarkAsRead(userID uuid.UUID, notificationID uuid.UUID) error
	MarkAllAsRead(userID uuid.UUID) error
	GetUnreadCount(userID uuid.UUID) (int, error)
	DeleteNotification(userID uuid.UUID, notificationID uuid.UUID) error
	DeleteAllNotifications(userID uuid.UUID) error
}

type NotificationHandlers struct {
	notificationService NotificationServiceInterface
}

func NewNotificationHandlers(notificationService *services.NotificationService) {
	NotificationHandlersInstance = &NotificationHandlers{
		notificationService: notificationService,
	}
}

// NewNotificationHandlersWithInterface creates new notification handlers with an interface (for testing)
func NewNotificationHandlersWithInterface(notificationService NotificationServiceInterface) *NotificationHandlers {
	return &NotificationHandlers{
		notificationService: notificationService,
	}
}

// GetNotifications retrieves all notifications for the authenticated user
// GET /api/v1/notifications
// BE-API-016: Implement notifications endpoints
func (nh *NotificationHandlers) GetNotifications(c *gin.Context) {
	userID, ok := GetUserIDUUID(c)
	if !ok {
		return // Erreur déjà envoyée par GetUserIDUUID
	}

	read := c.DefaultQuery("read", "")
	var unreadOnly bool
	if read == "false" {
		unreadOnly = true
	}

	notifications, err := nh.notificationService.GetNotifications(userID, unreadOnly)
	if err != nil {
		RespondWithAppError(c, apperrors.Wrap(apperrors.ErrCodeInternal, "Failed to get notifications", err))
		return
	}

	RespondSuccess(c, http.StatusOK, notifications)
}

// MarkAsRead marks a notification as read
// POST /api/v1/notifications/:id/read
// BE-API-016: Implement notifications endpoints
func (nh *NotificationHandlers) MarkAsRead(c *gin.Context) {
	userID, ok := GetUserIDUUID(c)
	if !ok {
		return // Erreur déjà envoyée par GetUserIDUUID
	}

	notificationID, err := uuid.Parse(c.Param("id"))
	if err != nil {
		RespondWithAppError(c, apperrors.NewValidationError("invalid notification id"))
		return
	}

	err = nh.notificationService.MarkAsRead(userID, notificationID)
	if err != nil {
		RespondWithAppError(c, apperrors.Wrap(apperrors.ErrCodeInternal, "Failed to mark notification as read", err))
		return
	}

	RespondSuccess(c, http.StatusOK, gin.H{"message": "Notification marked as read"})
}

// MarkAllAsRead marks all notifications as read for the user
// POST /api/v1/notifications/read-all
// BE-API-016: Implement notifications endpoints
func (nh *NotificationHandlers) MarkAllAsRead(c *gin.Context) {
	userID, ok := GetUserIDUUID(c)
	if !ok {
		return // Erreur déjà envoyée par GetUserIDUUID
	}

	if err := nh.notificationService.MarkAllAsRead(userID); err != nil {
		RespondWithAppError(c, apperrors.Wrap(apperrors.ErrCodeInternal, "Failed to mark all notifications as read", err))
		return
	}

	RespondSuccess(c, http.StatusOK, gin.H{"message": "All notifications marked as read"})
}

// GetUnreadCount returns the count of unread notifications
func (nh *NotificationHandlers) GetUnreadCount(c *gin.Context) {
	userID, ok := GetUserIDUUID(c)
	if !ok {
		return
	}

	count, err := nh.notificationService.GetUnreadCount(userID)
	if err != nil {
		RespondWithAppError(c, apperrors.Wrap(apperrors.ErrCodeInternal, "Failed to get unread count", err))
		return
	}

	RespondSuccess(c, http.StatusOK, gin.H{"count": count})
}

// DeleteNotification deletes a notification
func (nh *NotificationHandlers) DeleteNotification(c *gin.Context) {
	userID, ok := GetUserIDUUID(c)
	if !ok {
		return
	}

	notificationID, err := uuid.Parse(c.Param("id"))
	if err != nil {
		RespondWithAppError(c, apperrors.NewValidationError("invalid notification id"))
		return
	}

	err = nh.notificationService.DeleteNotification(userID, notificationID)
	if err != nil {
		RespondWithAppError(c, apperrors.Wrap(apperrors.ErrCodeInternal, "Failed to delete notification", err))
		return
	}

	RespondSuccess(c, http.StatusOK, gin.H{"message": "Notification deleted"})
}

// DeleteAllNotifications deletes all notifications for the user
func (nh *NotificationHandlers) DeleteAllNotifications(c *gin.Context) {
	userID, ok := GetUserIDUUID(c)
	if !ok {
		return
	}

	if err := nh.notificationService.DeleteAllNotifications(userID); err != nil {
		RespondWithAppError(c, apperrors.Wrap(apperrors.ErrCodeInternal, "Failed to delete all notifications", err))
		return
	}

	RespondSuccess(c, http.StatusOK, gin.H{"message": "All notifications deleted"})
}
