package handlers

import (
	"testing"

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

	"github.com/treytartt/honeydue-api/internal/config"
	"github.com/treytartt/honeydue-api/internal/services"
)

// newTestStorageService creates a StorageService with a known upload directory for testing.
// It does NOT call NewStorageService because that creates directories on disk.
// Instead, it directly constructs the struct with only what resolveFilePath needs.
func newTestStorageService(uploadDir string) *services.StorageService {
	cfg := &config.StorageConfig{
		UploadDir:    uploadDir,
		BaseURL:      "/uploads",
		MaxFileSize:  10 * 1024 * 1024,
		AllowedTypes: "image/jpeg,image/png",
	}
	// Use the exported constructor helper that skips directory creation (for tests)
	return services.NewStorageServiceForTest(cfg)
}

func TestResolveFilePath_NormalPath_Works(t *testing.T) {
	storageSvc := newTestStorageService("/var/uploads")
	h := NewMediaHandler(nil, nil, nil, storageSvc)

	result := h.resolveFilePath("images/photo.jpg")
	require.NotEmpty(t, result)
	assert.Equal(t, "/var/uploads/images/photo.jpg", result)
}

func TestResolveFilePath_LegacyUploadPath_Works(t *testing.T) {
	storageSvc := newTestStorageService("/var/uploads")
	h := NewMediaHandler(nil, nil, nil, storageSvc)

	result := h.resolveFilePath("/uploads/images/photo.jpg")
	require.NotEmpty(t, result)
	assert.Equal(t, "/var/uploads/images/photo.jpg", result)
}

func TestResolveFilePath_DotDotTraversal_Blocked(t *testing.T) {
	storageSvc := newTestStorageService("/var/uploads")
	h := NewMediaHandler(nil, nil, nil, storageSvc)

	tests := []struct {
		name      string
		storedURL string
	}{
		{"simple dotdot", "../etc/passwd"},
		{"nested dotdot", "../../etc/shadow"},
		{"embedded dotdot", "images/../../etc/passwd"},
		{"legacy prefix with dotdot", "/uploads/../../../etc/passwd"},
		{"deep dotdot", "a/b/c/../../../../etc/passwd"},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			result := h.resolveFilePath(tt.storedURL)
			assert.Empty(t, result, "path traversal should return empty string for: %s", tt.storedURL)
		})
	}
}

func TestResolveFilePath_EmptyURL_ReturnsEmpty(t *testing.T) {
	storageSvc := newTestStorageService("/var/uploads")
	h := NewMediaHandler(nil, nil, nil, storageSvc)

	result := h.resolveFilePath("")
	assert.Empty(t, result)
}
