package utils

import (
	"strings"
	"testing"

	"github.com/stretchr/testify/assert"
)

func TestValidatePlaylistTitle(t *testing.T) {
	tests := []struct {
		name      string
		title     string
		wantError bool
		errorType error
	}{
		{
			name:      "valid title",
			title:     "My Awesome Playlist",
			wantError: false,
		},
		{
			name:      "valid title with special characters",
			title:     "Playlist #1 - Best Songs",
			wantError: false,
		},
		{
			name:      "valid title exactly 200 characters",
			title:     strings.Repeat("a", 200),
			wantError: false,
		},
		{
			name:      "empty title",
			title:     "",
			wantError: true,
			errorType: ErrPlaylistTitleRequired,
		},
		{
			name:      "title with only spaces",
			title:     "   ",
			wantError: true,
			errorType: ErrPlaylistTitleRequired,
		},
		{
			name:      "title with only tabs",
			title:     "\t\t\t",
			wantError: true,
			errorType: ErrPlaylistTitleRequired,
		},
		{
			name:      "title too long",
			title:     strings.Repeat("a", 201),
			wantError: true,
			errorType: ErrPlaylistTitleTooLong,
		},
		{
			name:      "title with leading/trailing spaces but valid",
			title:     "  My Playlist  ",
			wantError: false,
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			err := ValidatePlaylistTitle(tt.title)
			if tt.wantError {
				assert.Error(t, err)
				if tt.errorType != nil {
					assert.Equal(t, tt.errorType, err)
				}
			} else {
				assert.NoError(t, err)
			}
		})
	}
}

func TestValidatePlaylistDescription(t *testing.T) {
	tests := []struct {
		name        string
		description string
		wantError   bool
		errorType   error
	}{
		{
			name:        "valid description",
			description: "This is a great playlist with amazing songs",
			wantError:   false,
		},
		{
			name:        "empty description",
			description: "",
			wantError:   false, // Description is optional
		},
		{
			name:        "valid description exactly 2000 characters",
			description: strings.Repeat("a", 2000),
			wantError:   false,
		},
		{
			name:        "description too long",
			description: strings.Repeat("a", 2001),
			wantError:   true,
			errorType:   ErrPlaylistDescTooLong,
		},
		{
			name:        "description with special characters",
			description: "Playlist with émojis 🎵 and special chars: !@#$%",
			wantError:   false,
		},
		{
			name:        "description with newlines",
			description: "Line 1\nLine 2\nLine 3",
			wantError:   false,
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			err := ValidatePlaylistDescription(tt.description)
			if tt.wantError {
				assert.Error(t, err)
				if tt.errorType != nil {
					assert.Equal(t, tt.errorType, err)
				}
			} else {
				assert.NoError(t, err)
			}
		})
	}
}

func TestValidateCoverURL(t *testing.T) {
	tests := []struct {
		name      string
		coverURL  string
		wantError bool
		errorType error
	}{
		{
			name:      "valid HTTPS URL",
			coverURL:  "https://example.com/cover.jpg",
			wantError: false,
		},
		{
			name:      "valid HTTP URL",
			coverURL:  "http://example.com/cover.jpg",
			wantError: false,
		},
		{
			name:      "valid URL with query parameters",
			coverURL:  "https://example.com/cover.jpg?w=500&h=500",
			wantError: false,
		},
		{
			name:      "valid URL with path",
			coverURL:  "https://cdn.example.com/images/covers/playlist-123.jpg",
			wantError: false,
		},
		{
			name:      "empty URL",
			coverURL:  "",
			wantError: false, // Cover URL is optional
		},
		{
			name:      "invalid URL - no scheme",
			coverURL:  "example.com/cover.jpg",
			wantError: true,
			errorType: ErrInvalidCoverURL,
		},
		{
			name:      "invalid URL - invalid scheme",
			coverURL:  "ftp://example.com/cover.jpg",
			wantError: true,
			errorType: ErrInvalidCoverURL,
		},
		{
			name:      "invalid URL - malformed",
			coverURL:  "not a valid url",
			wantError: true,
			errorType: ErrInvalidCoverURL,
		},
		{
			name:      "URL too long",
			coverURL:  "https://example.com/" + strings.Repeat("a", 500),
			wantError: true,
			errorType: ErrCoverURLTooLong,
		},
		{
			name:      "valid URL exactly 500 characters",
			coverURL:  "https://example.com/" + strings.Repeat("a", 500-22), // 22 = len("https://example.com/")
			wantError: false,
		},
		{
			name:      "invalid URL - file scheme",
			coverURL:  "file:///path/to/cover.jpg",
			wantError: true,
			errorType: ErrInvalidCoverURL,
		},
		{
			name:      "invalid URL - javascript scheme",
			coverURL:  "javascript:alert('xss')",
			wantError: true,
			errorType: ErrInvalidCoverURL,
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			err := ValidateCoverURL(tt.coverURL)
			if tt.wantError {
				assert.Error(t, err)
				if tt.errorType != nil {
					assert.Equal(t, tt.errorType, err)
				}
			} else {
				assert.NoError(t, err)
			}
		})
	}
}

// Test pour vérifier que les erreurs sont bien exportées
func TestPlaylistValidatorErrors(t *testing.T) {
	assert.NotNil(t, ErrPlaylistTitleRequired)
	assert.NotNil(t, ErrPlaylistTitleTooLong)
	assert.NotNil(t, ErrPlaylistDescTooLong)
	assert.NotNil(t, ErrInvalidCoverURL)
	assert.NotNil(t, ErrCoverURLTooLong)

	// Vérifier les messages d'erreur
	assert.Contains(t, ErrPlaylistTitleRequired.Error(), "title is required")
	assert.Contains(t, ErrPlaylistTitleTooLong.Error(), "title must be less than 200")
	assert.Contains(t, ErrPlaylistDescTooLong.Error(), "description must be less than 2000")
	assert.Contains(t, ErrInvalidCoverURL.Error(), "invalid cover URL")
	assert.Contains(t, ErrCoverURLTooLong.Error(), "cover URL must be less than 500")
}
