package com.atridad.openclimb.utils

import android.content.Context
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.net.Uri
import java.io.File
import java.io.FileOutputStream
import java.io.IOException
import java.util.UUID

object ImageUtils {
    
    private const val IMAGES_DIR = "problem_images"
    private const val MAX_IMAGE_SIZE = 1024
    private const val IMAGE_QUALITY = 85
    
    /**
     * Creates the images directory if it doesn't exist
     */
    private fun getImagesDirectory(context: Context): File {
        val imagesDir = File(context.filesDir, IMAGES_DIR)
        if (!imagesDir.exists()) {
            imagesDir.mkdirs()
        }
        return imagesDir
    }
    
    /**
     * Saves an image from URI to app's private storage with compression
     * @param context Android context
     * @param imageUri URI of the image to save
     * @return The relative file path if successful, null otherwise
     */
    fun saveImageFromUri(context: Context, imageUri: Uri): String? {
        return try {
            val inputStream = context.contentResolver.openInputStream(imageUri)
            inputStream?.use { input ->
                // Decode and compress the image
                val originalBitmap = BitmapFactory.decodeStream(input)
                val compressedBitmap = compressImage(originalBitmap)
                
                // Generate unique filename
                val filename = "${UUID.randomUUID()}.jpg"
                val imageFile = File(getImagesDirectory(context), filename)
                
                // Save compressed image
                FileOutputStream(imageFile).use { output ->
                    compressedBitmap.compress(Bitmap.CompressFormat.JPEG, IMAGE_QUALITY, output)
                }
                
                // Clean up bitmaps
                originalBitmap.recycle()
                compressedBitmap.recycle()
                
                // Return relative path
                "$IMAGES_DIR/$filename"
            }
        } catch (e: Exception) {
            e.printStackTrace()
            null
        }
    }
    
    /**
     * Compresses and resizes an image bitmap
     */
    private fun compressImage(original: Bitmap): Bitmap {
        val width = original.width
        val height = original.height
        
        // Calculate the scaling factor
        val scaleFactor = if (width > height) {
            if (width > MAX_IMAGE_SIZE) MAX_IMAGE_SIZE.toFloat() / width else 1f
        } else {
            if (height > MAX_IMAGE_SIZE) MAX_IMAGE_SIZE.toFloat() / height else 1f
        }
        
        return if (scaleFactor < 1f) {
            val newWidth = (width * scaleFactor).toInt()
            val newHeight = (height * scaleFactor).toInt()
            Bitmap.createScaledBitmap(original, newWidth, newHeight, true)
        } else {
            original
        }
    }
    
    /**
     * Gets the full file path for an image
     * @param context Android context
     * @param relativePath The relative path returned by saveImageFromUri
     * @return Full file path
     */
    fun getImageFile(context: Context, relativePath: String): File {
        return File(context.filesDir, relativePath)
    }
    
    /**
     * Deletes an image file
     * @param context Android context
     * @param relativePath The relative path of the image to delete
     * @return true if deleted successfully, false otherwise
     */
    fun deleteImage(context: Context, relativePath: String): Boolean {
        return try {
            val file = getImageFile(context, relativePath)
            file.delete()
        } catch (e: Exception) {
            e.printStackTrace()
            false
        }
    }
    
    /**
     * Copies an image file to export directory
     * @param context Android context
     * @param relativePath The relative path of the image
     * @param exportDir The directory to copy to
     * @return The filename in the export directory, null if failed
     */
    fun copyImageForExport(context: Context, relativePath: String, exportDir: File): String? {
        return try {
            val sourceFile = getImageFile(context, relativePath)
            if (!sourceFile.exists()) return null
            
            val filename = sourceFile.name
            val destFile = File(exportDir, filename)
            
            sourceFile.copyTo(destFile, overwrite = true)
            filename
        } catch (e: Exception) {
            e.printStackTrace()
            null
        }
    }
    
    /**
     * Imports an image file from the import directory
     * @param context Android context
     * @param sourceFile The source image file to import
     * @return The relative path in app storage, null if failed
     */
    fun importImageFile(context: Context, sourceFile: File): String? {
        return try {
            if (!sourceFile.exists()) return null
            
            // Generate new filename to avoid conflicts
            val extension = sourceFile.extension.ifEmpty { "jpg" }
            val filename = "${UUID.randomUUID()}.$extension"
            val destFile = File(getImagesDirectory(context), filename)
            
            sourceFile.copyTo(destFile, overwrite = true)
            "$IMAGES_DIR/$filename"
        } catch (e: Exception) {
            e.printStackTrace()
            null
        }
    }
    
    /**
     * Gets all image files in the images directory
     * @param context Android context
     * @return List of relative paths for all images
     */
    fun getAllImages(context: Context): List<String> {
        return try {
            val imagesDir = getImagesDirectory(context)
            imagesDir.listFiles()?.mapNotNull { file ->
                if (file.isFile && (file.extension == "jpg" || file.extension == "jpeg" || file.extension == "png")) {
                    "$IMAGES_DIR/${file.name}"
                } else null
            } ?: emptyList()
        } catch (e: Exception) {
            e.printStackTrace()
            emptyList()
        }
    }
    
    /**
     * Cleans up orphaned images that are not referenced by any problems
     * @param context Android context
     * @param referencedPaths Set of image paths that are still being used
     */
    fun cleanupOrphanedImages(context: Context, referencedPaths: Set<String>) {
        try {
            val allImages = getAllImages(context)
            val orphanedImages = allImages.filter { it !in referencedPaths }
            
            orphanedImages.forEach { path ->
                deleteImage(context, path)
            }
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }
}
