package com.rosetta.messenger.utils

import android.content.Context
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.util.Base64
import com.rosetta.messenger.crypto.CryptoManager
import java.io.ByteArrayOutputStream
import java.io.File
import java.security.MessageDigest

/**
 * Менеджер для работы с файлами аватаров
 * Совместимо с desktop версией:
 * - Все файлы зашифрованы паролем "rosetta-a"
 * - Формат пути: "a/md5hash" (без расширения)
 * - MD5 генерируется из (base64Image + entityId)
 */
object AvatarFileManager {
    
    private const val AVATAR_DIR = "avatars"
    private const val AVATAR_PASSWORD = "rosetta-a"
    private const val MAX_IMAGE_SIZE = 2048 // Максимальный размер изображения в пикселях
    private const val JPEG_QUALITY = 85 // Качество JPEG сжатия
    
    /**
     * Получить пароль для шифрования аватаров (для совместимости с desktop)
     */
    fun getAvatarPassword(): String = AVATAR_PASSWORD
    
    /**
     * Сохранить аватар в файловую систему
     * @param context Android context
     * @param base64Image Base64-encoded изображение
     * @param entityId ID сущности (publicKey или groupId)
     * @return Путь к файлу (формат: "a/md5hash")
     */
    fun saveAvatar(context: Context, base64Image: String, entityId: String): String {
        
        // Генерируем путь как в desktop версии
        val filePath = generateMd5Path(base64Image, entityId)
        
        // Шифруем данные с паролем "rosetta-a"
        val encrypted = CryptoManager.encryptWithPassword(base64Image, AVATAR_PASSWORD)
        
        // Сохраняем в файловую систему
        val dir = File(context.filesDir, AVATAR_DIR)
        dir.mkdirs()
        
        // Путь формата "a/md5hash" -> создаем подпапку "a"
        val parts = filePath.split("/")
        if (parts.size == 2) {
            val subDir = File(dir, parts[0])
            subDir.mkdirs()
            val file = File(subDir, parts[1])
            file.writeText(encrypted)
        } else {
            val file = File(dir, filePath)
            file.writeText(encrypted)
        }
        
        return filePath
    }
    
    /**
     * Прочитать и расшифровать аватар
     * @param context Android context
     * @param path Путь к файлу (формат: "a/md5hash")
     * @return Base64-encoded изображение или null
     */
    fun readAvatar(context: Context, path: String): String? {
        return try {
            val dir = File(context.filesDir, AVATAR_DIR)
            val file = File(dir, path)
            
            if (!file.exists()) return null
            
            val encrypted = file.readText()
            CryptoManager.decryptWithPassword(encrypted, AVATAR_PASSWORD)
        } catch (e: Exception) {
            null
        }
    }
    
    /**
     * Удалить файл аватара
     * @param context Android context
     * @param path Путь к файлу
     */
    fun deleteAvatar(context: Context, path: String) {
        try {
            val dir = File(context.filesDir, AVATAR_DIR)
            val file = File(dir, path)
            file.delete()
        } catch (e: Exception) {
            // Ignore errors
        }
    }
    
    /**
     * Проверить существует ли аватар по attachment ID (как в Desktop)
     * Desktop: readFile(`a/${md5(attachment.id + publicKey)}`)
     * 
     * @param context Android context
     * @param attachmentId ID attachment
     * @param publicKey Публичный ключ пользователя
     * @return true если файл существует
     */
    fun hasAvatarByAttachmentId(context: Context, attachmentId: String, publicKey: String): Boolean {
        val path = generatePathByAttachmentId(attachmentId, publicKey)
        val dir = File(context.filesDir, AVATAR_DIR)
        val file = File(dir, path)
        return file.exists()
    }
    
    /**
     * Прочитать аватар по attachment ID (как в Desktop)
     * Desktop: readFile(`a/${md5(attachment.id + publicKey)}`)
     * 
     * @param context Android context
     * @param attachmentId ID attachment
     * @param publicKey Публичный ключ пользователя
     * @return Base64-encoded изображение или null
     */
    fun readAvatarByAttachmentId(context: Context, attachmentId: String, publicKey: String): String? {
        val path = generatePathByAttachmentId(attachmentId, publicKey)
        return readAvatar(context, path)
    }
    
    /**
     * Сохранить аватар по attachment ID (как в Desktop)
     * Desktop: writeFile(`a/${md5(attachment.id + publicKey)}`, encrypted)
     * 
     * @param context Android context
     * @param base64Image Base64-encoded изображение
     * @param attachmentId ID attachment
     * @param publicKey Публичный ключ пользователя
     * @return Путь к файлу
     */
    fun saveAvatarByAttachmentId(context: Context, base64Image: String, attachmentId: String, publicKey: String): String {
        val path = generatePathByAttachmentId(attachmentId, publicKey)
        
        // Шифруем данные с паролем "rosetta-a"
        val encrypted = CryptoManager.encryptWithPassword(base64Image, AVATAR_PASSWORD)
        
        // Сохраняем в файловую систему
        val dir = File(context.filesDir, AVATAR_DIR)
        dir.mkdirs()
        
        val parts = path.split("/")
        if (parts.size == 2) {
            val subDir = File(dir, parts[0])
            subDir.mkdirs()
            val file = File(subDir, parts[1])
            file.writeText(encrypted)
        }
        
        return path
    }
    
    /**
     * Генерировать путь по attachment ID (как в Desktop)
     * Desktop: `a/${md5(attachment.id + publicKey)}`
     */
    private fun generatePathByAttachmentId(attachmentId: String, publicKey: String): String {
        val md5 = MessageDigest.getInstance("MD5")
            .digest("$attachmentId$publicKey".toByteArray())
            .joinToString("") { "%02x".format(it) }
        return "a/$md5"
    }
    
    /**
     * Генерировать MD5 путь для аватара (совместимо с desktop)
     * Desktop код:
     * ```js
     * const hash = md5(`${data}${entity}`);
     * return `a/${hash}`;
     * ```
     */
    fun generateMd5Path(data: String, entity: String): String {
        val md5 = MessageDigest.getInstance("MD5")
            .digest("$data$entity".toByteArray())
            .joinToString("") { "%02x".format(it) }
        return "a/$md5"
    }
    
    /**
     * Конвертировать URI изображения в Base64 PNG
     * Это соответствует desktop функции imagePrepareForNetworkTransfer()
     * которая конвертирует все изображения в PNG для кросс-платформенной совместимости
     * 
     * @param context Android context
     * @param imageData Данные изображения (может быть JPEG, PNG, etc.)
     * @return Base64-encoded PNG изображение
     */
    fun imagePrepareForNetworkTransfer(context: Context, imageData: ByteArray): String {
        // Декодируем изображение
        var bitmap = BitmapFactory.decodeByteArray(imageData, 0, imageData.size)
        
        // Ресайзим если слишком большое
        if (bitmap.width > MAX_IMAGE_SIZE || bitmap.height > MAX_IMAGE_SIZE) {
            val scale = MAX_IMAGE_SIZE.toFloat() / maxOf(bitmap.width, bitmap.height)
            val newWidth = (bitmap.width * scale).toInt()
            val newHeight = (bitmap.height * scale).toInt()
            bitmap = Bitmap.createScaledBitmap(bitmap, newWidth, newHeight, true)
        }
        
        // Конвертируем в PNG (для кросс-платформенной совместимости)
        val outputStream = ByteArrayOutputStream()
        bitmap.compress(Bitmap.CompressFormat.PNG, 100, outputStream)
        val pngBytes = outputStream.toByteArray()
        
        // Конвертируем в Base64
        return Base64.encodeToString(pngBytes, Base64.NO_WRAP)
    }
    
    /**
     * Конвертировать Base64 в Bitmap для отображения
     */
    fun base64ToBitmap(base64: String): Bitmap? {
        return try {
            // Check for data URI prefix
            val actualBase64 = if (base64.contains(",")) {
                base64.substringAfter(",")
            } else {
                base64
            }
            val imageBytes = Base64.decode(actualBase64, Base64.NO_WRAP)
            val bitmap = BitmapFactory.decodeByteArray(imageBytes, 0, imageBytes.size)
            bitmap
        } catch (e: Exception) {
            null
        }
    }
    
    /**
     * Получить размер файла в байтах
     */
    fun getFileSize(context: Context, path: String): Long {
        return try {
            val dir = File(context.filesDir, AVATAR_DIR)
            val file = File(dir, path)
            if (file.exists()) file.length() else 0
        } catch (e: Exception) {
            0
        }
    }
    
    /**
     * Очистить все аватары (для отладки)
     */
    fun clearAllAvatars(context: Context) {
        try {
            val dir = File(context.filesDir, AVATAR_DIR)
            dir.deleteRecursively()
        } catch (e: Exception) {
            // Ignore errors
        }
    }
}
