package handlers

import (
	"fmt"
	"net/http"
	"time"

	"github.com/gin-gonic/gin"
	"github.com/google/uuid"
	"go.uber.org/zap"

	"veza-backend-api/internal/services"
	"veza-backend-api/internal/workers"
)

// WebhookHandler gère les handlers de webhooks
type WebhookHandler struct {
	webhookService *services.WebhookService
	webhookWorker  *workers.WebhookWorker
	logger         *zap.Logger
	commonHandler  *CommonHandler
}

// NewWebhookHandler crée un nouveau handler de webhooks
func NewWebhookHandler(
	webhookService *services.WebhookService,
	webhookWorker *workers.WebhookWorker,
	logger *zap.Logger,
) *WebhookHandler {
	return &WebhookHandler{
		webhookService: webhookService,
		webhookWorker:  webhookWorker,
		logger:         logger,
		commonHandler:  NewCommonHandler(logger),
	}
}

// RegisterWebhook gère l'enregistrement d'un webhook
func (h *WebhookHandler) RegisterWebhook() gin.HandlerFunc {
	return func(c *gin.Context) {
		// Récupérer l'ID utilisateur
		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 type"})
			return
		}

		var req struct {
			URL    string   `json:"url" binding:"required,url"`
			Events []string `json:"events" binding:"required,min=1"`
		}

		if appErr := h.commonHandler.BindAndValidateJSON(c, &req); appErr != nil {
			RespondWithAppError(c, appErr)
			return
		}

		webhook, err := h.webhookService.RegisterWebhook(c.Request.Context(), userID, req.URL, req.Events)
		if err != nil {
			c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to register webhook"})
			return
		}

		c.JSON(http.StatusCreated, webhook)
	}
}

// ListWebhooks liste les webhooks d'un utilisateur
func (h *WebhookHandler) ListWebhooks() gin.HandlerFunc {
	return func(c *gin.Context) {
		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 type"})
			return
		}

		webhooks, err := h.webhookService.ListWebhooks(c.Request.Context(), userID)
		if err != nil {
			c.JSON(http.StatusInternalServerError, gin.H{"error": "Failed to list webhooks"})
			return
		}

		c.JSON(http.StatusOK, webhooks)
	}
}

// DeleteWebhook supprime un webhook
func (h *WebhookHandler) DeleteWebhook() gin.HandlerFunc {
	return func(c *gin.Context) {
		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 type"})
			return
		}

		webhookIDStr := c.Param("id")
		webhookID, err := uuid.Parse(webhookIDStr)
		if err != nil {
			c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid webhook ID"})
			return
		}

		err = h.webhookService.DeleteWebhook(c.Request.Context(), webhookID, userID)
		if err != nil {
			c.JSON(http.StatusNotFound, gin.H{"error": "Webhook not found"})
			return
		}

		c.JSON(http.StatusOK, gin.H{"message": "Webhook deleted successfully"})
	}
}

// GetWebhookStats retourne les statistiques des webhooks
func (h *WebhookHandler) GetWebhookStats() gin.HandlerFunc {
	return func(c *gin.Context) {
		stats := h.webhookWorker.GetStats()

		c.JSON(http.StatusOK, gin.H{
			"stats": stats,
		})
	}
}

// TestWebhook teste un webhook
func (h *WebhookHandler) TestWebhook() gin.HandlerFunc {
	return func(c *gin.Context) {
		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 type"})
			return
		}

		webhookIDStr := c.Param("id")
		webhookID, err := uuid.Parse(webhookIDStr)
		if err != nil {
			c.JSON(http.StatusBadRequest, gin.H{"error": "Invalid webhook ID"})
			return
		}

		webhook, err := h.webhookService.GetWebhook(c.Request.Context(), webhookID, userID)
		if err != nil {
			c.JSON(http.StatusNotFound, gin.H{"error": "Webhook not found"})
			return
		}

		job := workers.WebhookJob{
			Webhook: webhook,
			Event:   "ping",
			Data: map[string]interface{}{
				"message":   "This is a test webhook from Veza",
				"timestamp": time.Now(),
				"test_id":   uuid.New().String(),
			},
			Retries: 0,
		}

		h.webhookWorker.Enqueue(job)

		h.logger.Info("Test webhook queued", zap.String("webhook_id", webhookID.String()))

		c.JSON(http.StatusOK, gin.H{"message": fmt.Sprintf("Webhook test queued for %s", webhookID)})
	}
}
