package middleware

import (
	"context"

	"veza-backend-api/internal/models"
	"veza-backend-api/internal/response"

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

// PlaylistPermissionChecker définit l'interface pour vérifier les permissions de playlist
// T0484: Interface pour permettre le mocking dans les tests
// MIGRATION UUID: Utilise maintenant uuid.UUID au lieu de int64
type PlaylistPermissionChecker interface {
	CheckPermission(ctx context.Context, playlistID, userID uuid.UUID, 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 {
			response.Unauthorized(c, "unauthorized")
			c.Abort()
			return
		}

		// Extraire user_id comme uuid.UUID (défini par AuthMiddleware)
		// MIGRATION UUID: Support uuid.UUID directement, plus de conversion en int64
		var userID uuid.UUID
		switch v := userIDInterface.(type) {
		case uuid.UUID:
			userID = v
		case string:
			// Support legacy: si c'est une string, essayer de la parser en UUID
			parsed, err := uuid.Parse(v)
			if err != nil {
				response.Unauthorized(c, "invalid user id format")
				c.Abort()
				return
			}
			userID = parsed
		default:
			response.Unauthorized(c, "invalid user id type")
			c.Abort()
			return
		}

		// Extraire playlistID depuis les paramètres de la route
		// MIGRATION UUID: Parse playlistID comme UUID au lieu de int64
		playlistIDStr := c.Param("id")
		if playlistIDStr == "" {
			response.BadRequest(c, "playlist id is required")
			c.Abort()
			return
		}

		playlistID, err := uuid.Parse(playlistIDStr)
		if err != nil {
			response.BadRequest(c, "invalid playlist id format (expected UUID)")
			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" {
				response.NotFound(c, "playlist not found")
				c.Abort()
				return
			}
			response.InternalServerError(c, "failed to check permission")
			c.Abort()
			return
		}

		if !hasPermission {
			response.Forbidden(c, "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)
}
