package dev.kaizen.app.ui.theme

import android.graphics.Bitmap
import androidx.compose.runtime.Composable
import androidx.compose.runtime.remember
import androidx.compose.ui.graphics.ImageBitmap
import androidx.compose.ui.graphics.ImageShader
import androidx.compose.ui.graphics.ShaderBrush
import androidx.compose.ui.graphics.TileMode
import androidx.compose.ui.graphics.asImageBitmap
import kotlin.random.Random

/**
 * Cross-version gradient dither.
 *
 * 8-bit sRGB radial gradients quantize into visible concentric rings (the
 * "verpickelt"/banding look on the orb and mesh blobs). Overlaying a tiled,
 * ~1-LSB black/white/transparent noise pattern trades those hard bands for
 * imperceptible fine grain — the standard fix that works on every API level
 * (no AGSL / API-33 gating needed, so it covers minSdk 26).
 *
 * The pattern is deterministic (fixed seed) so it never shimmers between
 * recompositions; ~⅓ black, ⅓ white, ⅓ transparent makes the perturbation
 * symmetric (darkens and brightens equally) at a low overall [DITHER_ALPHA].
 *
 * [DITHER_ALPHA] is the single tuning knob: higher = bands vanish faster but
 * fine grain creeps in (worst on the near-black Obsidian background); lower =
 * cleaner but bands may survive. ~0.012–0.018 is the sweet spot — dial on device.
 */
const val DITHER_ALPHA = 0.015f

private fun buildNoiseBitmap(size: Int = 160): ImageBitmap {
    val pixels = IntArray(size * size)
    val rnd = Random(0x4A1B)
    for (i in pixels.indices) {
        pixels[i] = when (rnd.nextInt(3)) {
            0 -> 0xFF000000.toInt() // darken
            1 -> 0xFFFFFFFF.toInt() // brighten
            else -> 0x00000000      // leave untouched
        }
    }
    val bmp = Bitmap.createBitmap(size, size, Bitmap.Config.ARGB_8888)
    bmp.setPixels(pixels, 0, size, 0, 0, size, size)
    return bmp.asImageBitmap()
}

/** A tiled noise [ShaderBrush] for dithering. Build once, fill the whole surface at [DITHER_ALPHA]. */
@Composable
fun rememberDitherBrush(): ShaderBrush {
    val image = remember { buildNoiseBitmap() }
    return remember(image) { ShaderBrush(ImageShader(image, TileMode.Repeated, TileMode.Repeated)) }
}
