// internal/utils/image_handler.go
package utils

import (
	"errors"
	"fmt"
	"image"
	"image/jpeg"
	"image/png"
	"io"
	"mime/multipart"
	"os"
	"path/filepath"
	"strings"
	"time"
	"regexp"

	"github.com/nfnt/resize"
)

// ImageHandler handles image upload and processing
type ImageHandler struct {
	uploadPath    string
	maxSize       int64
	allowedTypes  []string
	maxWidth      uint
	maxHeight     uint
}

// NewImageHandler creates a new image handler
func NewImageHandler(uploadPath string) *ImageHandler {
	return &ImageHandler{
		uploadPath:   uploadPath,
		maxSize:      10 * 1024 * 1024, // 10MB
		allowedTypes: []string{"image/jpeg", "image/jpg", "image/png"},
		maxWidth:     1920,
		maxHeight:    1080,
	}
}

// UploadImage uploads and processes an image
// UploadImage uploads and processes an image
func (h *ImageHandler) UploadImage(file *multipart.FileHeader, subfolder string) (string, error) {
	// Check file size
	if file.Size > h.maxSize {
		return "", errors.New("file size exceeds maximum allowed size")
	}

	// Check file type
	if !h.isAllowedType(file.Header.Get("Content-Type")) {
		return "", errors.New("file type not allowed")
	}

	// Open uploaded file
	src, err := file.Open()
	if err != nil {
		return "", err
	}
	defer src.Close()

	// ✅ GENERATE FILENAME DENGAN TIMESTAMP
	ext := filepath.Ext(file.Filename)
	timestamp := time.Now().Format("20060102_150405") // Format: YYYYMMDD_HHMMSS
	baseFilename := strings.TrimSuffix(file.Filename, ext)
	
	// Remove special characters from filename
	baseFilename = sanitizeFilename(baseFilename)
	
	filename := fmt.Sprintf("%s_%s%s", baseFilename, timestamp, ext)

	// Create upload directory if not exists
	uploadDir := filepath.Join(h.uploadPath, subfolder)
	if err := os.MkdirAll(uploadDir, os.ModePerm); err != nil {
		return "", err
	}

	// Full file path
	filePath := filepath.Join(uploadDir, filename)

	// Decode image
	img, format, err := image.Decode(src)
	if err != nil {
		return "", errors.New("invalid image file")
	}

	// Resize if necessary
	if uint(img.Bounds().Dx()) > h.maxWidth || uint(img.Bounds().Dy()) > h.maxHeight {
		img = resize.Thumbnail(h.maxWidth, h.maxHeight, img, resize.Lanczos3)
	}

	// Create destination file
	dst, err := os.Create(filePath)
	if err != nil {
		return "", err
	}
	defer dst.Close()

	// Encode and save image
	switch format {
	case "jpeg", "jpg":
		if err := jpeg.Encode(dst, img, &jpeg.Options{Quality: 90}); err != nil {
			return "", err
		}
	case "png":
		if err := png.Encode(dst, img); err != nil {
			return "", err
		}
	default:
		return "", errors.New("unsupported image format")
	}

	// Return relative path
	return filepath.Join(subfolder, filename), nil
}

// ✅ TAMBAHKAN HELPER FUNCTION INI
func sanitizeFilename(filename string) string {
	// Remove special characters, keep only alphanumeric and hyphens
	reg := regexp.MustCompile(`[^a-zA-Z0-9\-]`)
	sanitized := reg.ReplaceAllString(filename, "")
	
	// Limit length
	if len(sanitized) > 50 {
		sanitized = sanitized[:50]
	}
	
	return sanitized
}

// UploadImageSimple uploads image without processing
func (h *ImageHandler) UploadImageSimple(file *multipart.FileHeader, subfolder string) (string, error) {
	// Check file size
	if file.Size > h.maxSize {
		return "", errors.New("file size exceeds maximum allowed size")
	}

	// Check file type
	if !h.isAllowedType(file.Header.Get("Content-Type")) {
		return "", errors.New("file type not allowed")
	}

	// Open uploaded file
	src, err := file.Open()
	if err != nil {
		return "", err
	}
	defer src.Close()

	// Generate unique filename
	ext := filepath.Ext(file.Filename)
	filename := fmt.Sprintf("%d_%s%s", time.Now().Unix(), generateRandomString(8), ext)

	// Create upload directory if not exists
	uploadDir := filepath.Join(h.uploadPath, subfolder)
	if err := os.MkdirAll(uploadDir, os.ModePerm); err != nil {
		return "", err
	}

	// Full file path
	filePath := filepath.Join(uploadDir, filename)

	// Create destination file
	dst, err := os.Create(filePath)
	if err != nil {
		return "", err
	}
	defer dst.Close()

	// Copy file
	if _, err := io.Copy(dst, src); err != nil {
		return "", err
	}

	// Return relative path
	return filepath.Join(subfolder, filename), nil
}

// DeleteImage deletes an image file
func (h *ImageHandler) DeleteImage(relativePath string) error {
	if relativePath == "" {
		return nil
	}

	filePath := filepath.Join(h.uploadPath, relativePath)
	if _, err := os.Stat(filePath); os.IsNotExist(err) {
		return nil // File doesn't exist, no error
	}

	return os.Remove(filePath)
}

// isAllowedType checks if file type is allowed
func (h *ImageHandler) isAllowedType(contentType string) bool {
	for _, allowed := range h.allowedTypes {
		if strings.EqualFold(contentType, allowed) {
			return true
		}
	}
	return false
}

// generateRandomString generates a random string
func generateRandomString(length int) string {
	const charset = "abcdefghijklmnopqrstuvwxyz0123456789"
	b := make([]byte, length)
	for i := range b {
		b[i] = charset[time.Now().UnixNano()%int64(len(charset))]
	}
	return string(b)
}