package handler

import (
	"net/http"

	"eslogad-be/internal/contract"
	"eslogad-be/internal/service"

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

type NotificationHandler struct {
	notificationService service.NotificationService
}

func NewNotificationHandler(notificationService service.NotificationService) *NotificationHandler {
	return &NotificationHandler{
		notificationService: notificationService,
	}
}

// TriggerNotification handles single notification trigger
func (h *NotificationHandler) TriggerNotification(c *gin.Context) {
	var req contract.TriggerNotificationRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	resp, err := h.notificationService.TriggerNotification(c.Request.Context(), &req)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	if !resp.Success {
		c.JSON(http.StatusBadRequest, gin.H{
			"success": false,
			"message": resp.Message,
		})
		return
	}

	c.JSON(http.StatusOK, resp)
}

// BulkTriggerNotification handles bulk notification trigger
func (h *NotificationHandler) BulkTriggerNotification(c *gin.Context) {
	var req contract.BulkTriggerNotificationRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	resp, err := h.notificationService.BulkTriggerNotification(c.Request.Context(), &req)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	c.JSON(http.StatusOK, resp)
}

// GetSubscriber retrieves subscriber information
func (h *NotificationHandler) GetSubscriber(c *gin.Context) {
	userIDStr := c.Param("userId")
	userID, err := uuid.Parse(userIDStr)
	if err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": "invalid user ID"})
		return
	}

	resp, err := h.notificationService.GetSubscriber(c.Request.Context(), userID)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	c.JSON(http.StatusOK, resp)
}

// UpdateSubscriberChannel updates subscriber channel credentials
func (h *NotificationHandler) UpdateSubscriberChannel(c *gin.Context) {
	var req contract.UpdateSubscriberChannelRequest
	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	resp, err := h.notificationService.UpdateSubscriberChannel(c.Request.Context(), &req)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	if !resp.Success {
		c.JSON(http.StatusBadRequest, gin.H{
			"success": false,
			"message": resp.Message,
		})
		return
	}

	c.JSON(http.StatusOK, resp)
}

// TriggerNotificationForCurrentUser triggers notification for the authenticated user
func (h *NotificationHandler) TriggerNotificationForCurrentUser(c *gin.Context) {
	// Get current user ID from context (set by auth middleware)
	userIDInterface, exists := c.Get("user_id")
	if !exists {
		c.JSON(http.StatusUnauthorized, gin.H{"error": "user not authenticated"})
		return
	}

	userID, ok := userIDInterface.(uuid.UUID)
	if !ok {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "invalid user ID in context"})
		return
	}

	var req struct {
		TemplateID   string                         `json:"template_id" validate:"required"`
		TemplateData map[string]interface{}         `json:"template_data,omitempty"`
		Overrides    *contract.NotificationOverrides `json:"overrides,omitempty"`
	}

	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	// Create trigger request with current user ID
	triggerReq := &contract.TriggerNotificationRequest{
		UserID:       userID,
		TemplateID:   req.TemplateID,
		TemplateData: req.TemplateData,
		Overrides:    req.Overrides,
	}

	resp, err := h.notificationService.TriggerNotification(c.Request.Context(), triggerReq)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	if !resp.Success {
		c.JSON(http.StatusBadRequest, gin.H{
			"success": false,
			"message": resp.Message,
		})
		return
	}

	c.JSON(http.StatusOK, resp)
}

// GetCurrentUserSubscriber retrieves subscriber information for the authenticated user
func (h *NotificationHandler) GetCurrentUserSubscriber(c *gin.Context) {
	// Get current user ID from context (set by auth middleware)
	userIDInterface, exists := c.Get("user_id")
	if !exists {
		c.JSON(http.StatusUnauthorized, gin.H{"error": "user not authenticated"})
		return
	}

	userID, ok := userIDInterface.(uuid.UUID)
	if !ok {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "invalid user ID in context"})
		return
	}

	resp, err := h.notificationService.GetSubscriber(c.Request.Context(), userID)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	c.JSON(http.StatusOK, resp)
}

// UpdateCurrentUserSubscriberChannel updates channel credentials for the authenticated user
func (h *NotificationHandler) UpdateCurrentUserSubscriberChannel(c *gin.Context) {
	// Get current user ID from context (set by auth middleware)
	userIDInterface, exists := c.Get("user_id")
	if !exists {
		c.JSON(http.StatusUnauthorized, gin.H{"error": "user not authenticated"})
		return
	}

	userID, ok := userIDInterface.(uuid.UUID)
	if !ok {
		c.JSON(http.StatusInternalServerError, gin.H{"error": "invalid user ID in context"})
		return
	}

	var req struct {
		Channel     string                 `json:"channel" validate:"required,oneof=email sms push chat in_app"`
		Credentials map[string]interface{} `json:"credentials" validate:"required"`
	}

	if err := c.ShouldBindJSON(&req); err != nil {
		c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()})
		return
	}

	// Create update request with current user ID
	updateReq := &contract.UpdateSubscriberChannelRequest{
		UserID:      userID,
		Channel:     req.Channel,
		Credentials: req.Credentials,
	}

	resp, err := h.notificationService.UpdateSubscriberChannel(c.Request.Context(), updateReq)
	if err != nil {
		c.JSON(http.StatusInternalServerError, gin.H{"error": err.Error()})
		return
	}

	if !resp.Success {
		c.JSON(http.StatusBadRequest, gin.H{
			"success": false,
			"message": resp.Message,
		})
		return
	}

	c.JSON(http.StatusOK, resp)
}