package middleware

import (
	"context"
	"net/http"
	"strconv"

	"github.com/gin-gonic/gin"
	"veza-backend-api/internal/models"
)

// PlaylistPermissionChecker définit l'interface pour vérifier les permissions de playlist
// T0484: Interface pour permettre le mocking dans les tests
type PlaylistPermissionChecker interface {
	CheckPermission(ctx context.Context, playlistID, userID int64, requiredPermission models.PlaylistPermission) (bool, error)
}

// CheckPlaylistPermission crée un middleware qui vérifie si un utilisateur a une permission spécifique sur une playlist
// T0484: Create Playlist Permission Middleware
// Le middleware vérifie:
// - Si l'utilisateur est le propriétaire (a toutes les permissions)
// - Si l'utilisateur est collaborateur avec la permission requise
// - Si la playlist est publique et la permission est "read"
func CheckPlaylistPermission(playlistService PlaylistPermissionChecker, requiredPermission models.PlaylistPermission) gin.HandlerFunc {
	return func(c *gin.Context) {
		// Récupérer user_id du contexte (doit être défini par AuthMiddleware)
		userIDInterface, exists := c.Get("user_id")
		if !exists {
			c.JSON(http.StatusUnauthorized, gin.H{"error": "unauthorized"})
			c.Abort()
			return
		}

		// Convertir user_id en int64
		var userID int64
		switch v := userIDInterface.(type) {
		case int64:
			userID = v
		case int:
			userID = int64(v)
		case float64:
			userID = int64(v)
		default:
			c.JSON(http.StatusUnauthorized, gin.H{"error": "invalid user id type"})
			c.Abort()
			return
		}

		// Extraire playlistID depuis les paramètres de la route
		playlistIDStr := c.Param("id")
		if playlistIDStr == "" {
			c.JSON(http.StatusBadRequest, gin.H{"error": "playlist id is required"})
			c.Abort()
			return
		}

		playlistID, err := strconv.ParseInt(playlistIDStr, 10, 64)
		if err != nil {
			c.JSON(http.StatusBadRequest, gin.H{"error": "invalid playlist id"})
			c.Abort()
			return
		}

		// Vérifier la permission via le service
		hasPermission, err := playlistService.CheckPermission(c.Request.Context(), playlistID, userID, requiredPermission)
		if err != nil {
			// Si la playlist n'existe pas, retourner 404
			if err.Error() == "playlist not found" {
				c.JSON(http.StatusNotFound, gin.H{"error": "playlist not found"})
				c.Abort()
				return
			}
			c.JSON(http.StatusInternalServerError, gin.H{"error": "failed to check permission"})
			c.Abort()
			return
		}

		if !hasPermission {
			c.JSON(http.StatusForbidden, gin.H{"error": "forbidden"})
			c.Abort()
			return
		}

		// Permission accordée, continuer
		c.Next()
	}
}

// RequirePlaylistOwner crée un middleware qui exige que l'utilisateur soit le propriétaire de la playlist
// T0484: Helper pour vérifier l'ownership
func RequirePlaylistOwner(playlistService PlaylistPermissionChecker) gin.HandlerFunc {
	return CheckPlaylistPermission(playlistService, models.PlaylistPermissionAdmin)
}

// RequirePlaylistWrite crée un middleware qui exige que l'utilisateur ait la permission write ou admin
// T0484: Helper pour vérifier la permission d'écriture
func RequirePlaylistWrite(playlistService PlaylistPermissionChecker) gin.HandlerFunc {
	return CheckPlaylistPermission(playlistService, models.PlaylistPermissionWrite)
}

// RequirePlaylistRead crée un middleware qui exige que l'utilisateur ait la permission read, write ou admin
// T0484: Helper pour vérifier la permission de lecture
func RequirePlaylistRead(playlistService PlaylistPermissionChecker) gin.HandlerFunc {
	return CheckPlaylistPermission(playlistService, models.PlaylistPermissionRead)
}
