package services

import (
	"bytes"
	"image/color"
	"image/jpeg"
	"testing"

	"github.com/disintegration/imaging"
	"go.uber.org/zap"
)

func TestNewEnhancedImageService(t *testing.T) {
	logger := zap.NewNop()
	service := NewEnhancedImageService(logger)

	if service == nil {
		t.Error("NewEnhancedImageService() returned nil")
	}
	if service.logger == nil {
		t.Error("NewEnhancedImageService() returned service with nil logger")
	}
}

func TestGetSizeDimensions(t *testing.T) {
	tests := []struct {
		name           string
		size           ImageSize
		expectedWidth  int
		expectedHeight int
	}{
		{
			name:           "thumbnail size",
			size:           SizeThumbnail,
			expectedWidth:  100,
			expectedHeight: 100,
		},
		{
			name:           "small size",
			size:           SizeSmall,
			expectedWidth:  200,
			expectedHeight: 200,
		},
		{
			name:           "medium size",
			size:           SizeMedium,
			expectedWidth:  400,
			expectedHeight: 400,
		},
		{
			name:           "large size",
			size:           SizeLarge,
			expectedWidth:  800,
			expectedHeight: 800,
		},
		{
			name:           "default size",
			size:           ImageSize("unknown"),
			expectedWidth:  200,
			expectedHeight: 200,
		},
	}

	for _, tt := range tests {
		t.Run(tt.name, func(t *testing.T) {
			width, height := GetSizeDimensions(tt.size)
			if width != tt.expectedWidth {
				t.Errorf("GetSizeDimensions() width = %d, want %d", width, tt.expectedWidth)
			}
			if height != tt.expectedHeight {
				t.Errorf("GetSizeDimensions() height = %d, want %d", height, tt.expectedHeight)
			}
		})
	}
}

func TestEnhancedImageService_resizeWithCropCenter(t *testing.T) {
	service := NewEnhancedImageService(zap.NewNop())

	// Create a test image (500x300)
	testImg := imaging.New(500, 300, color.RGBA{255, 0, 0, 255})

	// Resize to 200x200
	resized := service.resizeWithCropCenter(testImg, 200, 200)

	bounds := resized.Bounds()
	if bounds.Dx() != 200 {
		t.Errorf("resizeWithCropCenter() width = %d, want 200", bounds.Dx())
	}
	if bounds.Dy() != 200 {
		t.Errorf("resizeWithCropCenter() height = %d, want 200", bounds.Dy())
	}
}

func TestEnhancedImageService_resizeMaintainAspectRatio(t *testing.T) {
	service := NewEnhancedImageService(zap.NewNop())

	// Create a test image (500x300)
	testImg := imaging.New(500, 300, color.RGBA{255, 0, 0, 255})

	// Resize maintaining aspect ratio (max 200x200)
	resized := service.resizeMaintainAspectRatio(testImg, 200, 200)

	bounds := resized.Bounds()
	// Should maintain aspect ratio (5:3)
	// Width should be 200, height should be 120
	if bounds.Dx() != 200 {
		t.Errorf("resizeMaintainAspectRatio() width = %d, want 200", bounds.Dx())
	}
	if bounds.Dy() != 120 {
		t.Errorf("resizeMaintainAspectRatio() height = %d, want 120", bounds.Dy())
	}
}

func TestEnhancedImageService_encodeJPEG(t *testing.T) {
	service := NewEnhancedImageService(zap.NewNop())

	// Create a test image
	testImg := imaging.New(100, 100, color.RGBA{255, 0, 0, 255})

	// Encode as JPEG
	data, err := service.encodeJPEG(testImg, 85)
	if err != nil {
		t.Fatalf("encodeJPEG() error = %v", err)
	}

	if len(data) == 0 {
		t.Error("encodeJPEG() returned empty data")
	}

	// Verify it's valid JPEG
	_, err = jpeg.Decode(bytes.NewReader(data))
	if err != nil {
		t.Errorf("encodeJPEG() produced invalid JPEG: %v", err)
	}
}

func TestEnhancedImageService_encodePNG(t *testing.T) {
	service := NewEnhancedImageService(zap.NewNop())

	// Create a test image
	testImg := imaging.New(100, 100, color.RGBA{255, 0, 0, 255})

	// Encode as PNG
	data, err := service.encodePNG(testImg)
	if err != nil {
		t.Fatalf("encodePNG() error = %v", err)
	}

	if len(data) == 0 {
		t.Error("encodePNG() returned empty data")
	}
}

// TestEnhancedImageService_GetImageDimensions would require proper multipart.FileHeader mock
// This is tested indirectly through ProcessImage tests
// func TestEnhancedImageService_GetImageDimensions(t *testing.T) {
//     // Implementation would require multipart.FileHeader mock
// }

func TestImageProcessingOptions_Defaults(t *testing.T) {
	options := ImageProcessingOptions{}

	// Test that defaults are applied in ProcessImage method
	if options.Quality <= 0 || options.Quality > 100 {
		options.Quality = 85
	}
	if options.Format == "" {
		options.Format = FormatJPEG
	}
	if !options.MaintainAspectRatio {
		options.MaintainAspectRatio = true
	}
	if !options.CropCenter {
		options.CropCenter = true
	}

	if options.Quality != 85 {
		t.Errorf("Expected default quality 85, got %d", options.Quality)
	}
	if options.Format != FormatJPEG {
		t.Errorf("Expected default format JPEG, got %v", options.Format)
	}
}

// Note: Full integration tests would require:
// 1. Real image files (JPEG, PNG, WebP)
// 2. Multipart file headers
// 3. Verification of processed image dimensions and quality
// 4. Performance testing with large images
//
// Example integration test structure:
// func TestEnhancedImageService_ProcessImage_Integration(t *testing.T) {
//     // Create test image file
//     testImg := createTestImageFile(t, 1000, 1000)
//     defer os.Remove(testImg)
//
//     // Create multipart file header
//     fileHeader := createMultipartFileHeader(t, testImg)
//
//     service := NewEnhancedImageService(zap.NewNop())
//
//     ctx := context.Background()
//     options := ImageProcessingOptions{
//         Size:   SizeSmall,
//         Format: FormatJPEG,
//         Quality: 85,
//     }
//
//     result, err := service.ProcessImage(ctx, fileHeader, options)
//     if err != nil {
//         t.Fatalf("ProcessImage() error = %v", err)
//     }
//
//     if result.Width != 200 || result.Height != 200 {
//         t.Errorf("ProcessImage() dimensions = %dx%d, want 200x200", result.Width, result.Height)
//     }
//
//     if len(result.Data) == 0 {
//         t.Error("ProcessImage() returned empty data")
//     }
// }
