package com.dtourolle.jellytau.player

import android.content.Context
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.util.LruCache
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext
import java.net.HttpURLConnection
import java.net.URL

/**
 * Memory cache for album artwork bitmaps with LRU eviction.
 *
 * Features:
 * - LruCache for efficient memory usage (1/8 of heap, typically 12-16MB)
 * - Automatic bitmap scaling to 512x512 max (lock screen optimal size)
 * - Async HTTP downloads using Dispatchers.IO (non-blocking)
 * - Graceful error handling for network failures and corrupted images
 * - Singleton pattern for app-wide access
 *
 * Cache lifecycle: In-memory only, cleared on app termination.
 */
class AlbumArtCache(context: Context) {
    private val maxMemory = (Runtime.getRuntime().maxMemory() / 1024).toInt()
    private val cacheSize = maxMemory / 8  // Use 1/8 of available heap

    private val memoryCache = object : LruCache<String, Bitmap>(cacheSize) {
        override fun sizeOf(key: String, bitmap: Bitmap): Int {
            return bitmap.byteCount / 1024  // Size in KB
        }
    }

    /**
     * Get artwork bitmap for the given URL.
     *
     * Checks memory cache first, then downloads from network if not cached.
     * Scaling and error handling are done transparently.
     *
     * @param url The Jellyfin server artwork URL
     * @return The bitmap, or null if download failed or URL is invalid
     */
    suspend fun getArtwork(url: String): Bitmap? {
        // Check memory cache first
        memoryCache.get(url)?.let { return it }

        // Download from network if not cached
        return downloadAndCache(url)
    }

    /**
     * Download artwork from network and add to cache.
     *
     * Runs on IO dispatcher to avoid blocking the main thread.
     * Automatically scales large images to 512x512 max.
     * On failure, logs error and returns null.
     *
     * @param url The Jellyfin server artwork URL
     * @return The cached bitmap, or null if download/decode failed
     */
    private suspend fun downloadAndCache(url: String): Bitmap? = withContext(Dispatchers.IO) {
        try {
            val connection = URL(url).openConnection() as HttpURLConnection
            connection.doInput = true
            connection.connectTimeout = 5000
            connection.readTimeout = 5000
            connection.connect()

            if (connection.responseCode != HttpURLConnection.HTTP_OK) {
                android.util.Log.w("AlbumArtCache", "Failed to download artwork: HTTP ${connection.responseCode}")
                return@withContext null
            }

            val input = connection.inputStream
            val bitmap = BitmapFactory.decodeStream(input)
            input.close()
            connection.disconnect()

            bitmap?.let {
                // Scale down if too large (lock screen doesn't need full resolution)
                val scaled = scaleDownIfNeeded(it, MAX_ARTWORK_SIZE)
                memoryCache.put(url, scaled)
                android.util.Log.d("AlbumArtCache", "Cached artwork: ${scaled.width}x${scaled.height}")
                scaled
            }
        } catch (e: Exception) {
            android.util.Log.e("AlbumArtCache", "Failed to download artwork: ${e.message}", e)
            null
        }
    }

    /**
     * Scale down bitmap if it exceeds max size while maintaining aspect ratio.
     *
     * @param bitmap The original bitmap
     * @param maxSize Maximum width or height (e.g., 512)
     * @return Original bitmap if smaller than maxSize, else scaled version
     */
    private fun scaleDownIfNeeded(bitmap: Bitmap, maxSize: Int): Bitmap {
        if (bitmap.width <= maxSize && bitmap.height <= maxSize) return bitmap

        val ratio = minOf(
            maxSize.toFloat() / bitmap.width,
            maxSize.toFloat() / bitmap.height
        )

        val newWidth = (bitmap.width * ratio).toInt()
        val newHeight = (bitmap.height * ratio).toInt()

        return Bitmap.createScaledBitmap(bitmap, newWidth, newHeight, true)
    }

    /**
     * Clear all cached bitmaps from memory.
     *
     * Useful for memory-constrained situations or settings reset.
     */
    fun clear() {
        memoryCache.evictAll()
    }

    companion object {
        private const val MAX_ARTWORK_SIZE = 512  // 512x512 max for lock screen

        @Volatile
        private var instance: AlbumArtCache? = null

        /**
         * Get or create singleton instance.
         *
         * Thread-safe with double-checked locking pattern.
         *
         * @param context Android context for initialization
         * @return The singleton AlbumArtCache instance
         */
        fun getInstance(context: Context): AlbumArtCache {
            return instance ?: synchronized(this) {
                instance ?: AlbumArtCache(context).also { instance = it }
            }
        }
    }
}
