package com.img.rabbit.utils

import android.annotation.SuppressLint
import android.content.ContentValues
import android.content.Context
import android.content.Intent
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.net.Uri
import android.os.Build
import android.os.Environment
import android.provider.MediaStore
import android.util.Log
import java.io.File
import java.io.FileOutputStream
import java.io.IOException
import java.text.SimpleDateFormat
import java.util.*
import kotlin.apply

import android.graphics.*
import androidx.core.graphics.createBitmap
import com.img.rabbit.bean.local.LongImageBean
import java.io.ByteArrayOutputStream
import java.io.OutputStream

object ImageUtils {
    fun imageCompressToUri(context: Context, uri: Uri): ByteArray? {
        // 获取输入流并解码为Bitmap
        val inputStream = context.contentResolver.openInputStream(uri)
            ?: throw IOException("无法从Uri中读取文件(File)")

        val bitmap = inputStream.use { inputStream ->
            BitmapFactory.decodeStream(inputStream)
        } ?: throw IOException("无法解码图片")

        // 压缩图片 (JPEG格式，80%质量)
        val outputStream = ByteArrayOutputStream()
        bitmap.compress(Bitmap.CompressFormat.JPEG, 80, outputStream)
        val compressedByteArray = outputStream.toByteArray()
        bitmap.recycle() // 释放Bitmap内存

        // 使用压缩后的字节数组
        return compressedByteArray
    }

    fun decodeSampledBitmapFromResource(
        context: Context,
        resId: Int,
        reqWidth: Int,
        reqHeight: Int
    ): Bitmap {
        // 首先设置inJustDecodeBounds=true来获取图片尺寸
        val options = BitmapFactory.Options().apply {
            inJustDecodeBounds = true
        }
        BitmapFactory.decodeResource(context.resources, resId, options)

        // 计算inSampleSize
        options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight)
        Log.d("ImageUtils", "Sample size: ${options.inSampleSize}")

        // 根据计算的inSampleSize来解码图片
        options.inJustDecodeBounds = false
        return BitmapFactory.decodeResource(context.resources, resId, options)
    }

    // 新增：从byte数组加载图片的方法
    fun decodeSampledBitmapFromByteArray(
        byteArray: ByteArray,
        reqWidth: Int,
        reqHeight: Int
    ): Bitmap {
        // 首先设置inJustDecodeBounds=true来获取图片尺寸
        val options = BitmapFactory.Options().apply {
            inJustDecodeBounds = true
        }
        BitmapFactory.decodeByteArray(byteArray, 0, byteArray.size, options)

        // 计算inSampleSize
        options.inSampleSize = calculateInSampleSize(options, reqWidth, reqHeight)

        // 根据计算的inSampleSize来解码图片
        options.inJustDecodeBounds = false
        return BitmapFactory.decodeByteArray(byteArray, 0, byteArray.size, options)
    }

    private fun calculateInSampleSize(
        options: BitmapFactory.Options,
        reqWidth: Int,
        reqHeight: Int
    ): Int {
        // 原始图片的尺寸
        val height = options.outHeight
        val width = options.outWidth
        var inSampleSize = 1

        if (height > reqHeight || width > reqWidth) {
            val halfHeight = height / 2
            val halfWidth = width / 2

            // 计算最大的inSampleSize值，该值为2的幂，并保持
            // 高度和宽度均大于请求的高度和宽度
            while ((halfHeight / inSampleSize) >= reqHeight
                && (halfWidth / inSampleSize) >= reqWidth) {
                inSampleSize *= 2
            }
        }
        return inSampleSize
    }

    /**
     * 将Bitmap保存到设备存储
     * @param bitmap 要保存的Bitmap对象
     * @param context 上下文
     * @param format 图片格式（Bitmap.CompressFormat.JPEG 或 Bitmap.CompressFormat.PNG）
     * @param quality 压缩质量（0-100）
     * @return 保存的文件路径，如果保存失败则返回null
     */
    fun saveBitmapToStorage(
        bitmap: Bitmap,
        context: Context,
        format: Bitmap.CompressFormat = Bitmap.CompressFormat.PNG,
        quality: Int = 90
    ): String? {
        val timeStamp = SimpleDateFormat("yyyyMMdd_HHmmss", Locale.getDefault()).format(Date())
        val imageFileName = "JPEG_${timeStamp}_"
        
        return try {
            val imageFile: File
            val imagePath: String?
            
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
                // Android 10及以上使用MediaStore
                val contentValues = ContentValues().apply {
                    put(MediaStore.Images.Media.DISPLAY_NAME, "$imageFileName.${format.name.lowercase()}")
                    put(MediaStore.Images.Media.MIME_TYPE, "image/${format.name.lowercase()}")
                    put(MediaStore.Images.Media.RELATIVE_PATH, Environment.DIRECTORY_PICTURES + File.separator + "DoctorApp")
                }
                
                val resolver = context.contentResolver
                val imageUri: Uri? = resolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues)
                
                imageUri?.let { uri ->
                    resolver.openOutputStream(uri)?.use { outputStream ->
                        bitmap.compress(format, quality, outputStream)
                    }
                    return uri.toString()
                }
            } else {
                // Android 9及以下使用传统文件存储
                val storageDir = Environment.getExternalStoragePublicDirectory(Environment.DIRECTORY_PICTURES + File.separator + "DoctorApp")
                storageDir?.let { dir ->
                    if (!dir.exists() && !dir.mkdirs()) {
                        Log.e("ImageUtils", "无法创建存储目录")
                        return null
                    }
                    
                    imageFile = File(dir, "$imageFileName.${format.name.lowercase()}")
                    val outputStream = FileOutputStream(imageFile)
                    bitmap.compress(format, quality, outputStream)
                    outputStream.flush()
                    outputStream.close()
                    
                    // 将图片添加到媒体库
                    MediaStore.Images.Media.insertImage(context.contentResolver, imageFile.absolutePath, imageFile.name, null)
                    
                    // 通知媒体扫描器扫描文件
                    context.sendBroadcast(Intent(Intent.ACTION_MEDIA_SCANNER_SCAN_FILE, Uri.fromFile(imageFile)))
                    
                    return imageFile.absolutePath
                }
            }
            null
        } catch (e: IOException) {
            Log.e("ImageUtils", "保存图片失败", e)
            null
        }
    }

    /**
     * 将字节数组直接保存为图片文件
     * @param byteArray 图片字节数组
     * @param context 上下文
     * @param format 图片格式
     * @return 保存的文件路径，如果保存失败则返回null
     */
    fun saveByteArrayToStorage(
        byteArray: ByteArray,
        context: Context,
        format: Bitmap.CompressFormat = Bitmap.CompressFormat.PNG
    ): String? {
        return try {
            val bitmap = BitmapFactory.decodeByteArray(byteArray, 0, byteArray.size)
            saveBitmapToStorage(bitmap, context, format)
        } catch (e: Exception) {
            Log.e("ImageUtils", "保存字节数组为图片失败", e)
            null
        }
    }

    /**
     * 从URI获取Bitmap
     * @param context 上下文
     * @param uri 图片URI
     * @return Bitmap对象，如果获取失败则返回null
     */
    fun getBitmapFromUri(context: Context, uri: Uri): Bitmap? {
        return try {
            context.contentResolver.openInputStream(uri)?.use { inputStream ->
                BitmapFactory.decodeStream(inputStream)
            }
        } catch (e: Exception) {
            Log.e("ImageUtils", "从URI获取Bitmap失败", e)
            null
        }
    }

    /**
     * 将URI对应的图片保存到存储
     * @param context 上下文
     * @param uri 图片URI
     * @param format 图片格式
     * @param quality 压缩质量
     * @return 保存的文件路径，如果保存失败则返回null
     */
    fun saveUriToStorage(
        context: Context,
        uri: Uri,
        format: Bitmap.CompressFormat = Bitmap.CompressFormat.PNG,
        quality: Int = 90
    ): String? {
        return try {
            val bitmap = getBitmapFromUri(context, uri)
            bitmap?.let {
                saveBitmapToStorage(it, context, format, quality)
            }
        } catch (e: Exception) {
            Log.e("ImageUtils", "保存URI图片失败", e)
            null
        }
    }


    /**
     * 保存长图到相册
     * @param context 上下文
     * @param items 长图数据列表
     * @param format 导出格式
     * @param onSubmitResult 回调函数，用于通知保存结果
     */
    fun saveLongToGallery(
        context: Context,
        items: List<LongImageBean>,
        format: ExportFormat,
        onSubmitResult: (fileName: String, isSuccess: Boolean) -> Unit
    ) {
        if (items.isEmpty()) return

        // 1. 定义长图的统一输出宽度
        val canvasWidth = 1080f

        // 2. 计算每张图按比例缩放后的总高度
        var totalHeight = 0f
        val renderConfigs = items.map { item ->
            // 计算当前图片填满 1080 宽度所需的缩放比例
            val scale = canvasWidth / item.bitmap.width
            // 缩放后的实际物理高度
            val scaledHeight = item.bitmap.height * scale
            totalHeight += scaledHeight
            scale to scaledHeight
        }

        // 3. 创建大图画布
        val resultBitmap = Bitmap.createBitmap(canvasWidth.toInt(), totalHeight.toInt(), Bitmap.Config.ARGB_8888)
        val canvas = Canvas(resultBitmap)
        val paint = Paint(Paint.ANTI_ALIAS_FLAG) // 开启抗锯齿，防止缩放模糊
        var currentY = 0f

        // 4. 依次绘制每一张图片
        items.forEachIndexed { index, item ->
            val (scale, scaledHeight) = renderConfigs[index]

            val matrix = Matrix()
            // 先按比例缩放
            matrix.postScale(scale, scale)
            // 再平移到当前 Y 轴位置（实现无缝衔接）
            matrix.postTranslate(0f, currentY)

            canvas.drawBitmap(item.bitmap, matrix, paint)

            // 关键：累加【缩放后】的高度，确保下一张图紧贴上一张
            currentY += scaledHeight
        }

        // 5. 调用你原有的保存逻辑
        saveCanvasToGallery(context, resultBitmap, format, onSubmitResult)
    }


    /**
     * 保存位图到系统相册
     * @param context 上下文
     * @param bitmap 要保存的位图
     * @param format 导出格式（PNG/JPG）
     * @param onSubmitResult 回调函数，参数为文件名和是否成功
     */
    fun saveCanvasToGallery(
        context: Context,
        bitmap: Bitmap,
        format: ExportFormat,
        onSubmitResult: (fileName: String, isSuccess: Boolean) -> Unit
    ) {
        val extension = if (format == ExportFormat.JPG) "jpg" else "png"
        val mimeType = if (format == ExportFormat.JPG) "image/jpeg" else "image/png"
        val compressFormat = if (format == ExportFormat.JPG) Bitmap.CompressFormat.JPEG else Bitmap.CompressFormat.PNG

        val filename = "MyRabbit_${System.currentTimeMillis()}.$extension"

        val contentValues = ContentValues().apply {
            put(MediaStore.MediaColumns.DISPLAY_NAME, filename)
            put(MediaStore.MediaColumns.MIME_TYPE, mimeType)
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
                put(MediaStore.MediaColumns.RELATIVE_PATH, "DCIM/Camera")
            }
        }

        val uri = context.contentResolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues)
        uri?.let {
            context.contentResolver.openOutputStream(it)?.use { stream ->
                // PNG 忽略 quality 参数（无损），JPG 使用 100 表示最高质量
                bitmap.compress(compressFormat, 100, stream)
                onSubmitResult(filename, true)
            }
        } ?: run {
            onSubmitResult(filename, false)
        }
    }

    /**
     * 保存位图到系统相册（如果targetWidth与targetHeight比原始值小太多会导致图片模糊）
     * @param context 上下文
     * @param bitmap 要保存的位图
     * @param format 导出格式（PNG/JPG）
     * @param targetWidth 目标宽度
     * @param targetHeight 目标高度
     * @param onSubmitResult 回调函数，参数为文件名和是否成功
     */
    @SuppressLint("UseKtx")
    fun saveCanvasToGallery(
        context: Context,
        bitmap: Bitmap,
        format: ExportFormat,
        targetWidth: Int,
        targetHeight: Int,
        onSubmitResult: (fileName: String, isSuccess: Boolean) -> Unit
    ) {
        // 1. 修复 Hardware Bitmap 报错并确保使用 ARGB_8888 高精度配置
        val softwareBitmap = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O &&
            bitmap.config == Bitmap.Config.HARDWARE) {
            bitmap.copy(Bitmap.Config.ARGB_8888, false)
        } else {
            // 如果不是硬件位图，也建议检查并转换为高精度配置以防模糊
            bitmap
        }

        val extension = if (format == ExportFormat.JPG) "jpg" else "png"
        val mimeType = if (format == ExportFormat.JPG) "image/jpeg" else "image/png"
        val compressFormat = if (format == ExportFormat.JPG) Bitmap.CompressFormat.JPEG else Bitmap.CompressFormat.PNG

        // 2. 创建目标尺寸位图 (显式指定 Config.ARGB_8888 保证清晰度)
        val scaledResult = Bitmap.createBitmap(targetWidth, targetHeight, Bitmap.Config.ARGB_8888)
        val canvas = Canvas(scaledResult)

        // 3. 处理背景色 (如果是 JPG 填充白色，PNG 保持透明)
        if (format == ExportFormat.JPG) {
            canvas.drawColor(Color.WHITE)
        }

        // 4. 【核心算法：计算等比例缩放】
        val srcWidth = softwareBitmap.width.toFloat()
        val srcHeight = softwareBitmap.height.toFloat()

        // 使用 float 计算比例，避免整数除法丢失精度导致模糊
        val scale = (targetWidth.toFloat() / srcWidth).coerceAtMost(targetHeight.toFloat() / srcHeight)

        val finalWidth = srcWidth * scale
        val finalHeight = srcHeight * scale
        val left = (targetWidth - finalWidth) / 2f
        val top = (targetHeight - finalHeight) / 2f

        // 5. 【关键：高清绘制配置】
        val paint = Paint().apply {
            isAntiAlias = true        // 开启抗锯齿，边缘更平滑
            isFilterBitmap = true     // 开启位图过滤，这是解决缩放模糊的最核心设置
            isDither = true           // 开启抖动，色彩过渡更自然
        }

        val destRect = RectF(left, top, left + finalWidth, top + finalHeight)
        // 绘图
        canvas.drawBitmap(softwareBitmap, null, destRect, paint)

        // 6. 保存到 MediaStore
        val filename = "MyRabbit_${System.currentTimeMillis()}.$extension"
        val contentValues = ContentValues().apply {
            put(MediaStore.MediaColumns.DISPLAY_NAME, filename)
            put(MediaStore.MediaColumns.MIME_TYPE, mimeType)
            if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
                put(MediaStore.MediaColumns.RELATIVE_PATH, "DCIM/Camera")
            }
        }

        val uri = context.contentResolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues)

        try {
            uri?.let {
                context.contentResolver.openOutputStream(it)?.use { stream ->
                    // 100 表示不压缩质量
                    scaledResult.compress(compressFormat, 100, stream)
                    onSubmitResult(filename, true)
                }
            } ?: onSubmitResult(filename, false)
        } catch (e: Exception) {
            e.printStackTrace()
            onSubmitResult(filename, false)
        } finally {
            // 7. 内存回收
            if (softwareBitmap != bitmap) softwareBitmap.recycle()
            // 注意：如果后面还要用 scaledResult，不要在这里 recycle
            // scaledResult.recycle()
        }
    }

    /**
     * 转换为相册可保存的格式（PNG/JPG/SVG/GIF）
     * @param context 上下文
     * @param sourceBitmap 原始位图
     * @param format 导出格式（PNG/JPG/SVG/GIF）
     * @param onSubmitResult 回调函数，参数为文件名和是否成功
     */
    fun convertToGallery(
        context: Context,
        sourceBitmap: Bitmap,
        format: ExportFormat,
        onSubmitResult: (fileName: String, isSuccess: Boolean) -> Unit
    ) {
        // 1. 预处理：缩放并获得高清软件位图（防止 Hardware Bitmap 报错）
        val softwareBitmap = if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.O && sourceBitmap.config == Bitmap.Config.HARDWARE) {
            sourceBitmap.copy(Bitmap.Config.ARGB_8888, false)
        } else sourceBitmap

        val scaledBitmap = createScaledBitmap(softwareBitmap, sourceBitmap.width, sourceBitmap.height)

        // 2. 准备 MediaStore 容器
        val filename = "MyRabbit_Export_${System.currentTimeMillis()}.${format.extension}"
        val contentValues = if (format == ExportFormat.SVG) {
            ContentValues().apply {
                put(MediaStore.MediaColumns.DISPLAY_NAME, filename)
                put(MediaStore.MediaColumns.MIME_TYPE, "image/svg+xml") // 关键：SVG 的 MIME 类型
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
                    put(MediaStore.MediaColumns.RELATIVE_PATH, "DCIM/Camera")
                }
            }
        }else{
            ContentValues().apply {
                put(MediaStore.MediaColumns.DISPLAY_NAME, filename)
                put(MediaStore.MediaColumns.MIME_TYPE, format.mimeType)
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
                    put(MediaStore.MediaColumns.RELATIVE_PATH, "DCIM/Camera")
                }
            }
        }

        val uri = context.contentResolver.insert(MediaStore.Images.Media.EXTERNAL_CONTENT_URI, contentValues)

        // 3. 根据格式执行不同的转换编码
        try {
            uri?.let {
                context.contentResolver.openOutputStream(it)?.use { stream ->
                    when (format) {
                        ExportFormat.JPG -> scaledBitmap.compress(Bitmap.CompressFormat.JPEG, 100, stream)
                        ExportFormat.PNG -> scaledBitmap.compress(Bitmap.CompressFormat.PNG, 100, stream)
                        ExportFormat.GIF -> encodeToGif(scaledBitmap, stream)
                        ExportFormat.SVG -> encodeToSvg(scaledBitmap, stream)
                    }
                    onSubmitResult(filename, true)
                }
            } ?: onSubmitResult(filename, false)
        } catch (e: Exception) {
            onSubmitResult(e.message ?: "Unknown Error", false)
        }
    }


    /**
     * 创建等比例适配的缩放位图
     * @param src 原始位图
     * @param destW 目标宽度
     * @param destH 目标高度
     * @return 缩放后的位图
     */
    private fun createScaledBitmap(src: Bitmap, destW: Int, destH: Int): Bitmap {
        val result = createBitmap(destW, destH)
        val canvas = Canvas(result)
        val paint = Paint(Paint.ANTI_ALIAS_FLAG or Paint.FILTER_BITMAP_FLAG or Paint.DITHER_FLAG)

        // 等比例适配逻辑
        val scale = (destW.toFloat() / src.width).coerceAtMost(destH.toFloat() / src.height)
        val left = (destW - src.width * scale) / 2f
        val top = (destH - src.height * scale) / 2f

        canvas.drawBitmap(src, null, RectF(left, top, left + src.width * scale, top + src.height * scale), paint)
        return result
    }

    /**
     * 具体的 GIF 编码逻辑
     * @param bitmap 原始位图
     * @param outputStream 输出流
     */
    private fun encodeToGif(bitmap: Bitmap, outputStream: OutputStream) {
        // Android 原生不支持直接写 GIF，通常需使用外部库或简单的 Bitmap 压缩
        // 这里演示通过 Bitmap 压缩模拟格式导出逻辑
        try {
            // 注意：Android 原生 compress 不支持 GIF 格式，
            // 实际开发中若需生成多帧 GIF，建议使用 'jp.co.cyberagent.android:gpuimage' 或第三方编码器
            bitmap.compress(Bitmap.CompressFormat.PNG, 100, outputStream)
            outputStream.flush()
            outputStream.close()
        } catch (e: Exception) {
            e.printStackTrace()
        }
    }

    /**
     * 具体的 SVG 编码逻辑
     * @param bitmap 原始位图
     * @param stream 输出流
     */
    private fun encodeToSvg(bitmap: Bitmap, stream: OutputStream) {
        try {
            val width = bitmap.width
            val height = bitmap.height

            val bos = ByteArrayOutputStream()
            // 使用 PNG 保证透明度
            bitmap.compress(Bitmap.CompressFormat.PNG, 100, bos)

            // 必须使用 NO_WRAP 标志，如果不加 NO_WRAP，Base64 字符串每 76 个字符会插入一个换行符，导致 SVG 标签断开
            val base64Data = android.util.Base64.encodeToString(bos.toByteArray(), android.util.Base64.NO_WRAP)

            // XML 命名空间地址
            val svgContent = """
        <?xml version="1.0" encoding="UTF-8"?>
        <svg width="$width" height="$height" viewBox="0 0 $width $height" 
             xmlns="http://www.w3.org/2000/svg" 
             xmlns:xlink="http://www.w3.org/1999/xlink">
            <image width="$width" height="$height" 
                   xlink:href="data:image/png;base64,$base64Data" 
                   href="data:image/png;base64,$base64Data" />
        </svg>
    """.trimIndent()

            stream.write(svgContent.toByteArray(Charsets.UTF_8))
            stream.flush()
        } catch (e: Exception) {
            Log.e("ImageUtils", "SVG 编码失败: ${e.message}")
            throw e
        }
    }

}

enum class ExportFormat(val extension: String, val mimeType: String) {
    JPG("jpg", "image/jpeg"),
    PNG("png", "image/png"),
    GIF("gif", "image/gif"),
    SVG("svg", "image/svg+xml")
}

