Pith - shim
package com.vgmlr.shim

import android.content.Context
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Typography
import androidx.compose.material3.darkColorScheme
import androidx.compose.runtime.Composable
import androidx.compose.runtime.mutableFloatStateOf
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.ui.graphics.Color
import androidx.core.content.edit
import androidx.core.graphics.toColorInt

internal const val SPACING_DEFAULT = 14
internal const val TAG_BG_DEFAULT = "#324540"

@Composable
fun ShimTheme(
    themeManager: ShimThemeManager,
    content: @Composable () -> Unit
) {
    val colorScheme = darkColorScheme(
        primary = Color(0xFF486860),
        background = themeManager.backgroundColor.value,
        onBackground = themeManager.textColor.value,
        surface = themeManager.backgroundColor.value,
        onSurface = themeManager.textColor.value
    )

    MaterialTheme(
        colorScheme = colorScheme,
        typography = Typography(),
        content = content
    )
}

class ShimThemeManager(private val context: Context) {
    private val prefs = context.getSharedPreferences("shim_prefs", Context.MODE_PRIVATE)

    var backgroundColor = mutableStateOf(Color(context.getColor(R.color.background_color)))
    var textColor = mutableStateOf(Color(context.getColor(R.color.text_color)))
    var tagBgColor = mutableStateOf(Color(TAG_BG_DEFAULT.toColorInt()))
    var fontSize = mutableFloatStateOf(15.5f)
    var isMonospace = mutableStateOf(false)
    var showDates = mutableStateOf(false)
    var lineHeight = mutableFloatStateOf(1.3f)
    var lineSpacing = mutableFloatStateOf(0.2f)
    var shimSpacing = mutableIntStateOf(SPACING_DEFAULT)

    var hexBgColor = "#%06X".format(0xFFFFFF and context.getColor(R.color.background_color))
    var hexTextColor = "#%06X".format(0xFFFFFF and context.getColor(R.color.text_color))
    var hexTagBgColor = TAG_BG_DEFAULT

    init {
        refresh()
    }

    private fun getSafeString(key: String, default: String): String =
        prefs.getString(key, default) ?: default

    private fun formatHex(hex: String): String = if (hex.startsWith("#")) hex else "#$hex"
    private fun formatNum(num: String): String = num.replace(Regex("[^0-9.]"), "")

    fun saveTheme(
        bg: String,
        text: String,
        tagBg: String,
        mono: Boolean,
        size: String,
        height: String,
        spacing: String,
        gap: String,
        dates: Boolean
    ) {
        prefs.edit {
            putString("main_background", formatHex(bg))
            putString("main_color", formatHex(text))
            putString("tag_bg", formatHex(tagBg))
            putBoolean("is_monospace", mono)
            putString("main_size", formatNum(size))
            putString("line_height", height)
            putString("line_spacing", spacing)
            putString("shim_spacing", formatNum(gap))
            putBoolean("show_dates", dates)
        }
        refresh()
    }

    fun refresh() {
        val defaultBg = "#%06X".format(0xFFFFFF and context.getColor(R.color.background_color))
        val defaultText = "#%06X".format(0xFFFFFF and context.getColor(R.color.text_color))

        hexBgColor = getSafeString("main_background", defaultBg)
        hexTextColor = getSafeString("main_color", defaultText)
        hexTagBgColor = getSafeString("tag_bg", TAG_BG_DEFAULT)

        backgroundColor.value = try {
            Color(hexBgColor.toColorInt())
        } catch (_: Exception) {
            Color(context.getColor(R.color.background_color))
        }
        textColor.value = try {
            Color(hexTextColor.toColorInt())
        } catch (_: Exception) {
            Color(context.getColor(R.color.text_color))
        }
        tagBgColor.value = try {
            Color(hexTagBgColor.toColorInt())
        } catch (_: Exception) {
            Color(TAG_BG_DEFAULT.toColorInt())
        }

        isMonospace.value = prefs.getBoolean("is_monospace", false)
        showDates.value = prefs.getBoolean("show_dates", false)
        fontSize.floatValue = getSafeString("main_size", "15.5").toFloatOrNull() ?: 15.5f
        lineHeight.floatValue = getSafeString("line_height", "1.35").toFloatOrNull() ?: 1.35f
        lineSpacing.floatValue = getSafeString("line_spacing", "0.2").toFloatOrNull() ?: 0.2f
        shimSpacing.intValue =
            getSafeString("shim_spacing", "$SPACING_DEFAULT").toIntOrNull() ?: SPACING_DEFAULT
    }
}