package handlers

import (
	"bytes"
	"context"
	"encoding/json"
	"fmt"
	"net/http"
	"net/http/httptest"
	"testing"
	"time"

	"github.com/google/uuid"

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

	"github.com/gin-gonic/gin"
	"github.com/stretchr/testify/assert"
	"github.com/stretchr/testify/require"
	"go.uber.org/zap"
	"gorm.io/driver/sqlite"
	"gorm.io/gorm"
)

// setupPlaylistCollaborationIntegrationTestRouter crée un router de test avec tous les handlers nécessaires
func setupPlaylistCollaborationIntegrationTestRouter(t *testing.T) (*gin.Engine, *gorm.DB, func()) {
	gin.SetMode(gin.TestMode)

	// Setup in-memory SQLite database
	db, err := gorm.Open(sqlite.Open(":memory:"), &gorm.Config{})
	require.NoError(t, err)

	// Enable foreign keys for SQLite
	db.Exec("PRAGMA foreign_keys = ON")

	// Auto-migrate all models
	err = db.AutoMigrate(
		&models.User{},
		&models.Playlist{},
		&models.PlaylistTrack{},
		&models.PlaylistCollaborator{},
	)
	require.NoError(t, err)

	// Setup logger
	logger := zap.NewNop()

	// Setup service
	playlistService := services.NewPlaylistServiceWithDB(db, logger)
	playlistHandler := NewPlaylistHandler(playlistService, db, logger)

	// Setup router
	router := gin.New()
	router.Use(func(c *gin.Context) {
		// Mock authentication middleware - set user_id from query param
		if userIDStr := c.Query("user_id"); userIDStr != "" {
			uid, err := uuid.Parse(userIDStr)
			if err == nil {
				c.Set("user_id", uid)
			}
		}
		c.Next()
	})

	// Setup routes
	v1 := router.Group("/api/v1")
	{
		v1.POST("/playlists/:id/collaborators", playlistHandler.AddCollaborator)
		v1.GET("/playlists/:id/collaborators", playlistHandler.GetCollaborators)
		v1.DELETE("/playlists/:id/collaborators/:userId", playlistHandler.RemoveCollaborator)
		v1.PUT("/playlists/:id/collaborators/:userId", playlistHandler.UpdateCollaboratorPermission)
		v1.POST("/playlists/:id/share", playlistHandler.CreateShareLink)
	}

	// Cleanup function
	cleanup := func() {
		// Database will be closed automatically
	}

	return router, db, cleanup
}

// createTestUser crée un utilisateur de test
func createTestUserForCollaboration(t *testing.T, db *gorm.DB, userID uuid.UUID, username string) *models.User {
	user := &models.User{
		ID:           userID,
		Username:     username,
		Email:        username + "@example.com",
		PasswordHash: "hashed_password",
		Slug:         username,
		IsActive:     true,
		CreatedAt:    time.Now(),
	}
	err := db.Create(user).Error
	require.NoError(t, err)
	return user
}

// createTestPlaylist crée une playlist de test
func createTestPlaylistForCollaboration(t *testing.T, db *gorm.DB, userID uuid.UUID, playlistID uuid.UUID) *models.Playlist {
	playlist := &models.Playlist{
		ID:          playlistID,
		UserID:      userID,
		Title:       "Test Playlist",
		Description: "Test Description",
		IsPublic:    true,
		TrackCount:  0,
		CreatedAt:   time.Now(),
		UpdatedAt:   time.Now(),
	}
	err := db.Create(playlist).Error
	require.NoError(t, err)
	return playlist
}

// TestPlaylistCollaborationIntegration_AddCollaborator teste l'ajout d'un collaborateur
func TestPlaylistCollaborationIntegration_AddCollaborator(t *testing.T) {
	if testing.Short() {
		t.Skip("Skipping integration test in short mode")
	}

	router, db, cleanup := setupPlaylistCollaborationIntegrationTestRouter(t)
	defer cleanup()

	// Créer des utilisateurs de test
	ownerID := uuid.New()
	collaboratorID := uuid.New()
	createTestUserForCollaboration(t, db, ownerID, "owner")
	createTestUserForCollaboration(t, db, collaboratorID, "collaborator")

	// Créer une playlist
	playlistID := uuid.New()
	createTestPlaylistForCollaboration(t, db, ownerID, playlistID)

	// Test 1: Ajouter un collaborateur avec permission read
	reqBody := AddCollaboratorRequest{
		UserID:     collaboratorID,
		Permission: "read",
	}
	body, err := json.Marshal(reqBody)
	require.NoError(t, err)

	req := httptest.NewRequest("POST", fmt.Sprintf("/api/v1/playlists/%s/collaborators?user_id=%s", playlistID, ownerID), bytes.NewBuffer(body))
	req.Header.Set("Content-Type", "application/json")
	w := httptest.NewRecorder()
	router.ServeHTTP(w, req)

	assert.Equal(t, http.StatusCreated, w.Code)
	var response map[string]interface{}
	err = json.Unmarshal(w.Body.Bytes(), &response)
	require.NoError(t, err)
	// MOD-P0-002: Accéder au format de réponse standardisé {success: true, data: {collaborator: {...}}}
	assert.Contains(t, response, "data")
	data, ok := response["data"].(map[string]interface{})
	require.True(t, ok, "response should contain 'data' key with map value")
	assert.NotNil(t, data["collaborator"])
	var collaborator models.PlaylistCollaborator
	err = db.Where("playlist_id = ? AND user_id = ?", playlistID, collaboratorID).First(&collaborator).Error
	require.NoError(t, err)
	assert.Equal(t, models.PlaylistPermissionRead, collaborator.Permission)

	// Test 2: Essayer d'ajouter le même collaborateur (devrait échouer)
	req = httptest.NewRequest("POST", fmt.Sprintf("/api/v1/playlists/%s/collaborators?user_id=%s", playlistID, ownerID), bytes.NewBuffer(body))
	req.Header.Set("Content-Type", "application/json")
	w = httptest.NewRecorder()
	router.ServeHTTP(w, req)

	assert.Equal(t, http.StatusConflict, w.Code)

	// Test 3: Essayer d'ajouter un collaborateur sans être propriétaire (devrait échouer)
	otherUserID := uuid.New()
	createTestUserForCollaboration(t, db, otherUserID, "other_user")
	req = httptest.NewRequest("POST", fmt.Sprintf("/api/v1/playlists/%s/collaborators?user_id=%s", playlistID, otherUserID), bytes.NewBuffer(body))
	req.Header.Set("Content-Type", "application/json")
	w = httptest.NewRecorder()
	router.ServeHTTP(w, req)

	assert.Equal(t, http.StatusForbidden, w.Code)
}

// TestPlaylistCollaborationIntegration_RemoveCollaborator teste la suppression d'un collaborateur
func TestPlaylistCollaborationIntegration_RemoveCollaborator(t *testing.T) {
	if testing.Short() {
		t.Skip("Skipping integration test in short mode")
	}

	router, db, cleanup := setupPlaylistCollaborationIntegrationTestRouter(t)
	defer cleanup()

	// Créer des utilisateurs de test
	ownerID := uuid.New()
	collaboratorID := uuid.New()
	createTestUserForCollaboration(t, db, ownerID, "owner")
	createTestUserForCollaboration(t, db, collaboratorID, "collaborator")

	// Créer une playlist
	playlistID := uuid.New()
	createTestPlaylistForCollaboration(t, db, ownerID, playlistID)

	// Ajouter un collaborateur via le service directement
	playlistService := services.NewPlaylistServiceWithDB(db, zap.NewNop())
	_, err := playlistService.AddCollaborator(context.Background(), playlistID, ownerID, collaboratorID, models.PlaylistPermissionRead)
	require.NoError(t, err)

	// Test 1: Retirer le collaborateur
	req := httptest.NewRequest("DELETE", fmt.Sprintf("/api/v1/playlists/%s/collaborators/%s?user_id=%s", playlistID, collaboratorID, ownerID), nil) // Changed context.Background() to nil as per common httptest usage
	w := httptest.NewRecorder()
	router.ServeHTTP(w, req)

	assert.Equal(t, http.StatusOK, w.Code)
	var response map[string]interface{}
	err = json.Unmarshal(w.Body.Bytes(), &response)
	require.NoError(t, err)
	// MOD-P0-002: Accéder au format de réponse standardisé {success: true, data: {message: "..."}}
	assert.Contains(t, response, "data")
	data, ok := response["data"].(map[string]interface{})
	require.True(t, ok, "response should contain 'data' key with map value")
	assert.Equal(t, "collaborator removed", data["message"])

	// Vérifier que le collaborateur a été supprimé
	var count int64
	db.Model(&models.PlaylistCollaborator{}).Where("playlist_id = ? AND user_id = ?", playlistID, collaboratorID).Count(&count)
	assert.Equal(t, int64(0), count)

	// Test 2: Essayer de retirer un collaborateur inexistant (devrait échouer)
	req = httptest.NewRequest("DELETE", fmt.Sprintf("/api/v1/playlists/%s/collaborators/%s?user_id=%s", playlistID, collaboratorID, ownerID), nil) // Changed context.Background() to nil
	w = httptest.NewRecorder()
	router.ServeHTTP(w, req)

	assert.Equal(t, http.StatusNotFound, w.Code)

	// Test 3: Essayer de retirer un collaborateur sans être propriétaire (devrait échouer)
	// Réajouter le collaborateur
	_, err = playlistService.AddCollaborator(context.Background(), playlistID, ownerID, collaboratorID, models.PlaylistPermissionRead)
	require.NoError(t, err)

	otherUserID := uuid.New()
	createTestUserForCollaboration(t, db, otherUserID, "other_user")
	req = httptest.NewRequest("DELETE", fmt.Sprintf("/api/v1/playlists/%s/collaborators/%s?user_id=%s", playlistID, collaboratorID, otherUserID), nil)
	w = httptest.NewRecorder()
	router.ServeHTTP(w, req)

	assert.Equal(t, http.StatusForbidden, w.Code)
}

// TestPlaylistCollaborationIntegration_UpdatePermission teste la mise à jour de la permission d'un collaborateur
func TestPlaylistCollaborationIntegration_UpdatePermission(t *testing.T) {
	if testing.Short() {
		t.Skip("Skipping integration test in short mode")
	}

	router, db, cleanup := setupPlaylistCollaborationIntegrationTestRouter(t)
	defer cleanup()

	// Créer des utilisateurs de test
	ownerID := uuid.New()
	collaboratorID := uuid.New()
	createTestUserForCollaboration(t, db, ownerID, "owner")
	createTestUserForCollaboration(t, db, collaboratorID, "collaborator")

	// Créer une playlist
	playlistID := uuid.New()
	createTestPlaylistForCollaboration(t, db, ownerID, playlistID)

	// Ajouter un collaborateur avec permission read
	playlistService := services.NewPlaylistServiceWithDB(db, zap.NewNop())
	_, err := playlistService.AddCollaborator(context.Background(), playlistID, ownerID, collaboratorID, models.PlaylistPermissionRead)
	require.NoError(t, err)

	// Test 1: Mettre à jour la permission à write
	reqBody := UpdateCollaboratorPermissionRequest{
		Permission: "write",
	}
	body, err := json.Marshal(reqBody)
	require.NoError(t, err)

	req := httptest.NewRequest("PUT", fmt.Sprintf("/api/v1/playlists/%s/collaborators/%s?user_id=%s", playlistID, collaboratorID, ownerID), bytes.NewBuffer(body))
	req.Header.Set("Content-Type", "application/json")
	w := httptest.NewRecorder()
	router.ServeHTTP(w, req)

	assert.Equal(t, http.StatusOK, w.Code)
	var response map[string]interface{}
	err = json.Unmarshal(w.Body.Bytes(), &response)
	require.NoError(t, err)
	// MOD-P0-002: Accéder au format de réponse standardisé {success: true, data: {message: "..."}}
	assert.Contains(t, response, "data")
	data, ok := response["data"].(map[string]interface{})
	require.True(t, ok, "response should contain 'data' key with map value")
	assert.Equal(t, "collaborator permission updated", data["message"])

	// Vérifier que la permission a été mise à jour
	var collaborator models.PlaylistCollaborator
	err = db.Where("playlist_id = ? AND user_id = ?", playlistID, collaboratorID).First(&collaborator).Error
	require.NoError(t, err)
	assert.Equal(t, models.PlaylistPermissionWrite, collaborator.Permission)

	// Test 2: Mettre à jour la permission à admin
	reqBody.Permission = "admin"
	body, err = json.Marshal(reqBody)
	require.NoError(t, err)

	req = httptest.NewRequest("PUT", fmt.Sprintf("/api/v1/playlists/%s/collaborators/%s?user_id=%s", playlistID, collaboratorID, ownerID), bytes.NewBuffer(body))
	req.Header.Set("Content-Type", "application/json")
	w = httptest.NewRecorder()
	router.ServeHTTP(w, req)

	assert.Equal(t, http.StatusOK, w.Code)

	// Vérifier que la permission a été mise à jour
	err = db.Where("playlist_id = ? AND user_id = ?", playlistID, collaboratorID).First(&collaborator).Error
	require.NoError(t, err)
	assert.Equal(t, models.PlaylistPermissionAdmin, collaborator.Permission)

	// Test 3: Essayer de mettre à jour sans être propriétaire (devrait échouer)
	otherUserID := uuid.New()
	createTestUserForCollaboration(t, db, otherUserID, "other_user")
	req = httptest.NewRequest("PUT", fmt.Sprintf("/api/v1/playlists/%s/collaborators/%s?user_id=%s", playlistID, collaboratorID, otherUserID), bytes.NewBuffer(body))
	req.Header.Set("Content-Type", "application/json")
	w = httptest.NewRecorder()
	router.ServeHTTP(w, req)

	assert.Equal(t, http.StatusForbidden, w.Code)
}

// TestPlaylistCollaborationIntegration_GetCollaborators teste la récupération des collaborateurs
func TestPlaylistCollaborationIntegration_GetCollaborators(t *testing.T) {
	if testing.Short() {
		t.Skip("Skipping integration test in short mode")
	}

	router, db, cleanup := setupPlaylistCollaborationIntegrationTestRouter(t)
	defer cleanup()

	// Créer des utilisateurs de test
	ownerID := uuid.New()
	collaborator1ID := uuid.New()
	collaborator2ID := uuid.New()
	createTestUserForCollaboration(t, db, ownerID, "owner")
	createTestUserForCollaboration(t, db, collaborator1ID, "collaborator1")
	createTestUserForCollaboration(t, db, collaborator2ID, "collaborator2")

	// Créer une playlist
	playlistID := uuid.New()
	createTestPlaylistForCollaboration(t, db, ownerID, playlistID)

	// Ajouter des collaborateurs
	playlistService := services.NewPlaylistServiceWithDB(db, zap.NewNop())
	_, err := playlistService.AddCollaborator(context.Background(), playlistID, ownerID, collaborator1ID, models.PlaylistPermissionRead)
	require.NoError(t, err)
	_, err = playlistService.AddCollaborator(context.Background(), playlistID, ownerID, collaborator2ID, models.PlaylistPermissionWrite)
	require.NoError(t, err)

	// Test 1: Récupérer les collaborateurs en tant que propriétaire
	req := httptest.NewRequest("GET", fmt.Sprintf("/api/v1/playlists/%s/collaborators?user_id=%s", playlistID, ownerID), nil)
	w := httptest.NewRecorder()
	router.ServeHTTP(w, req)

	assert.Equal(t, http.StatusOK, w.Code)
	var response map[string]interface{}
	err = json.Unmarshal(w.Body.Bytes(), &response)
	require.NoError(t, err)
	// MOD-P0-002: Accéder au format de réponse standardisé {success: true, data: {collaborators: [...]}}
	assert.Contains(t, response, "data")
	data, ok := response["data"].(map[string]interface{})
	require.True(t, ok, "response should contain 'data' key with map value")
	require.NotNil(t, data["collaborators"])
	collaborators := data["collaborators"].([]interface{})
	assert.Len(t, collaborators, 2)

	// Test 2: Récupérer les collaborateurs en tant que collaborateur
	req = httptest.NewRequest("GET", fmt.Sprintf("/api/v1/playlists/%s/collaborators?user_id=%s", playlistID, collaborator1ID), nil)
	w = httptest.NewRecorder()
	router.ServeHTTP(w, req)

	assert.Equal(t, http.StatusOK, w.Code)
	err = json.Unmarshal(w.Body.Bytes(), &response)
	require.NoError(t, err)
	// MOD-P0-002: Accéder au format de réponse standardisé {success: true, data: {collaborators: [...]}}
	assert.Contains(t, response, "data")
	data2, ok := response["data"].(map[string]interface{})
	require.True(t, ok, "response should contain 'data' key with map value")
	require.NotNil(t, data2["collaborators"])

	// Test 3: Essayer de récupérer les collaborateurs d'une playlist privée sans accès (devrait échouer)
	privatePlaylistID := uuid.New()
	privatePlaylist := createTestPlaylistForCollaboration(t, db, ownerID, privatePlaylistID)
	privatePlaylist.IsPublic = false
	db.Save(privatePlaylist)

	otherUserID := uuid.New()
	createTestUserForCollaboration(t, db, otherUserID, "other_user")
	req = httptest.NewRequest("GET", fmt.Sprintf("/api/v1/playlists/%s/collaborators?user_id=%s", privatePlaylistID, otherUserID), nil)
	w = httptest.NewRecorder()
	router.ServeHTTP(w, req)

	assert.Equal(t, http.StatusForbidden, w.Code)
}

// TestPlaylistCollaborationIntegration_CheckPermission teste la vérification des permissions
func TestPlaylistCollaborationIntegration_CheckPermission(t *testing.T) {
	if testing.Short() {
		t.Skip("Skipping integration test in short mode")
	}

	router, db, cleanup := setupPlaylistCollaborationIntegrationTestRouter(t)
	defer cleanup()

	// Créer des utilisateurs de test
	ownerID := uuid.New()
	collaboratorReadID := uuid.New()
	collaboratorWriteID := uuid.New()
	collaboratorAdminID := uuid.New()
	createTestUserForCollaboration(t, db, ownerID, "owner")
	createTestUserForCollaboration(t, db, collaboratorReadID, "collaborator_read")
	createTestUserForCollaboration(t, db, collaboratorWriteID, "collaborator_write")
	createTestUserForCollaboration(t, db, collaboratorAdminID, "collaborator_admin")

	// Créer une playlist
	playlistID := uuid.New()
	createTestPlaylistForCollaboration(t, db, ownerID, playlistID)

	// Ajouter des collaborateurs avec différentes permissions
	playlistService := services.NewPlaylistServiceWithDB(db, zap.NewNop())
	_, err := playlistService.AddCollaborator(context.Background(), playlistID, ownerID, collaboratorReadID, models.PlaylistPermissionRead)
	require.NoError(t, err)
	_, err = playlistService.AddCollaborator(context.Background(), playlistID, ownerID, collaboratorWriteID, models.PlaylistPermissionWrite)
	require.NoError(t, err)
	_, err = playlistService.AddCollaborator(context.Background(), playlistID, ownerID, collaboratorAdminID, models.PlaylistPermissionAdmin)
	require.NoError(t, err)

	// Test 1: Vérifier que le propriétaire peut récupérer les collaborateurs (a toutes les permissions)
	req := httptest.NewRequest("GET", fmt.Sprintf("/api/v1/playlists/%s/collaborators?user_id=%s", playlistID, ownerID), nil)
	w := httptest.NewRecorder()
	router.ServeHTTP(w, req)
	assert.Equal(t, http.StatusOK, w.Code)

	// Test 2: Vérifier que le collaborateur read peut récupérer les collaborateurs
	req = httptest.NewRequest("GET", fmt.Sprintf("/api/v1/playlists/%s/collaborators?user_id=%s", playlistID, collaboratorReadID), nil)
	w = httptest.NewRecorder()
	router.ServeHTTP(w, req)
	assert.Equal(t, http.StatusOK, w.Code)

	// Test 3: Vérifier que le collaborateur write peut récupérer les collaborateurs
	req = httptest.NewRequest("GET", fmt.Sprintf("/api/v1/playlists/%s/collaborators?user_id=%s", playlistID, collaboratorWriteID), nil)
	w = httptest.NewRecorder()
	router.ServeHTTP(w, req)
	assert.Equal(t, http.StatusOK, w.Code)

	// Test 4: Vérifier que le collaborateur admin peut récupérer les collaborateurs
	req = httptest.NewRequest("GET", fmt.Sprintf("/api/v1/playlists/%s/collaborators?user_id=%s", playlistID, collaboratorAdminID), nil)
	w = httptest.NewRecorder()
	router.ServeHTTP(w, req)
	assert.Equal(t, http.StatusOK, w.Code)

	// Test 5: Vérifier qu'un utilisateur non collaborateur peut récupérer les collaborateurs d'une playlist publique
	otherUserID := uuid.New()
	createTestUserForCollaboration(t, db, otherUserID, "other_user")
	req = httptest.NewRequest("GET", fmt.Sprintf("/api/v1/playlists/%s/collaborators?user_id=%s", playlistID, otherUserID), nil)
	w = httptest.NewRecorder()
	router.ServeHTTP(w, req)
	assert.Equal(t, http.StatusOK, w.Code)
}

// TestPlaylistCollaborationIntegration_CompleteFlow teste le flux complet de collaboration
func TestPlaylistCollaborationIntegration_CompleteFlow(t *testing.T) {
	if testing.Short() {
		t.Skip("Skipping integration test in short mode")
	}

	router, db, cleanup := setupPlaylistCollaborationIntegrationTestRouter(t)
	defer cleanup()

	// Créer des utilisateurs de test
	ownerID := uuid.New()
	collaboratorID := uuid.New()
	createTestUserForCollaboration(t, db, ownerID, "owner")
	createTestUserForCollaboration(t, db, collaboratorID, "collaborator")

	// Créer une playlist
	playlistID := uuid.New()
	createTestPlaylistForCollaboration(t, db, ownerID, playlistID)

	// Étape 1: Ajouter un collaborateur avec permission read
	reqBody := AddCollaboratorRequest{
		UserID:     collaboratorID,
		Permission: "read",
	}
	body, err := json.Marshal(reqBody)
	require.NoError(t, err)

	req := httptest.NewRequest("POST", fmt.Sprintf("/api/v1/playlists/%s/collaborators?user_id=%s", playlistID, ownerID), bytes.NewBuffer(body))
	req.Header.Set("Content-Type", "application/json")
	w := httptest.NewRecorder()
	router.ServeHTTP(w, req)
	assert.Equal(t, http.StatusCreated, w.Code)

	// Étape 2: Vérifier que le collaborateur peut récupérer les collaborateurs
	req = httptest.NewRequest("GET", fmt.Sprintf("/api/v1/playlists/%s/collaborators?user_id=%s", playlistID, collaboratorID), nil)
	w = httptest.NewRecorder()
	router.ServeHTTP(w, req)
	assert.Equal(t, http.StatusOK, w.Code)

	// Étape 3: Mettre à jour la permission à write
	updateReqBody := UpdateCollaboratorPermissionRequest{
		Permission: "write",
	}
	updateBody, err := json.Marshal(updateReqBody)
	require.NoError(t, err)

	req = httptest.NewRequest("PUT", fmt.Sprintf("/api/v1/playlists/%s/collaborators/%s?user_id=%s", playlistID, collaboratorID, ownerID), bytes.NewBuffer(updateBody))
	req.Header.Set("Content-Type", "application/json")
	w = httptest.NewRecorder()
	router.ServeHTTP(w, req)
	assert.Equal(t, http.StatusOK, w.Code)

	// Étape 4: Vérifier que la permission a été mise à jour
	var collaborator models.PlaylistCollaborator
	err = db.Where("playlist_id = ? AND user_id = ?", playlistID, collaboratorID).First(&collaborator).Error
	require.NoError(t, err)
	assert.Equal(t, models.PlaylistPermissionWrite, collaborator.Permission)

	// Étape 5: Retirer le collaborateur
	req = httptest.NewRequest("DELETE", fmt.Sprintf("/api/v1/playlists/%s/collaborators/%s?user_id=%s", playlistID, collaboratorID, ownerID), nil)
	w = httptest.NewRecorder()
	router.ServeHTTP(w, req)
	assert.Equal(t, http.StatusOK, w.Code)

	// Étape 6: Vérifier que le collaborateur a été supprimé
	var count int64
	db.Model(&models.PlaylistCollaborator{}).Where("playlist_id = ? AND user_id = ?", playlistID, collaboratorID).Count(&count)
	assert.Equal(t, int64(0), count)
}

// TestPlaylistCollaborationIntegration_CreateShareLink teste la création d'un lien de partage
func TestPlaylistCollaborationIntegration_CreateShareLink(t *testing.T) {
	if testing.Short() {
		t.Skip("Skipping integration test in short mode")
	}

	router, db, cleanup := setupPlaylistCollaborationIntegrationTestRouter(t)
	defer cleanup()

	// Créer des utilisateurs de test
	ownerID := uuid.New()
	collaboratorID := uuid.New()
	createTestUserForCollaboration(t, db, ownerID, "owner")
	createTestUserForCollaboration(t, db, collaboratorID, "collaborator")

	// Créer une playlist
	playlistID := uuid.New()
	createTestPlaylistForCollaboration(t, db, ownerID, playlistID)

	// Test 1: Créer un lien de partage en tant que propriétaire
	req := httptest.NewRequest("POST", fmt.Sprintf("/api/v1/playlists/%s/share?user_id=%s", playlistID, ownerID), nil)
	w := httptest.NewRecorder()
	router.ServeHTTP(w, req)

	assert.Equal(t, http.StatusOK, w.Code)
	var response map[string]interface{}
	err := json.Unmarshal(w.Body.Bytes(), &response)
	require.NoError(t, err)
	assert.Contains(t, response, "data")
	data, ok := response["data"].(map[string]interface{})
	require.True(t, ok)
	assert.Contains(t, data, "share_token")
	assert.Contains(t, data, "share_url")

	// Test 2: Essayer de créer un lien de partage sans être propriétaire (devrait échouer)
	req = httptest.NewRequest("POST", fmt.Sprintf("/api/v1/playlists/%s/share?user_id=%s", playlistID, collaboratorID), nil)
	w = httptest.NewRecorder()
	router.ServeHTTP(w, req)

	assert.Equal(t, http.StatusForbidden, w.Code)

	// Test 3: Essayer de créer un lien de partage pour une playlist inexistante (devrait échouer)
	nonExistentPlaylistID := uuid.New()
	req = httptest.NewRequest("POST", fmt.Sprintf("/api/v1/playlists/%s/share?user_id=%s", nonExistentPlaylistID, ownerID), nil)
	w = httptest.NewRecorder()
	router.ServeHTTP(w, req)

	assert.Equal(t, http.StatusNotFound, w.Code)
}

// TestPlaylistCollaborationIntegration_ShareLinkWithCollaborator teste le partage avec collaborateur admin
func TestPlaylistCollaborationIntegration_ShareLinkWithCollaborator(t *testing.T) {
	if testing.Short() {
		t.Skip("Skipping integration test in short mode")
	}

	router, db, cleanup := setupPlaylistCollaborationIntegrationTestRouter(t)
	defer cleanup()

	// Créer des utilisateurs de test
	ownerID := uuid.New()
	adminCollaboratorID := uuid.New()
	createTestUserForCollaboration(t, db, ownerID, "owner")
	createTestUserForCollaboration(t, db, adminCollaboratorID, "admin_collaborator")

	// Créer une playlist
	playlistID := uuid.New()
	createTestPlaylistForCollaboration(t, db, ownerID, playlistID)

	// Ajouter un collaborateur avec permission admin
	playlistService := services.NewPlaylistServiceWithDB(db, zap.NewNop())
	_, err := playlistService.AddCollaborator(context.Background(), playlistID, ownerID, adminCollaboratorID, models.PlaylistPermissionAdmin)
	require.NoError(t, err)

	// Test: Créer un lien de partage en tant que collaborateur admin (devrait réussir)
	req := httptest.NewRequest("POST", fmt.Sprintf("/api/v1/playlists/%s/share?user_id=%s", playlistID, adminCollaboratorID), nil)
	w := httptest.NewRecorder()
	router.ServeHTTP(w, req)

	// Note: Le service vérifie si l'utilisateur est owner ou admin collaborator
	// Si le service permet aux admin collaborators de créer des share links, cela devrait réussir
	// Sinon, cela devrait retourner 403
	// Pour l'instant, on vérifie que la requête est traitée (pas d'erreur 500)
	assert.True(t, w.Code == http.StatusOK || w.Code == http.StatusForbidden)
}
