package top.yeij.cyrene.ui.theme

import androidx.compose.material3.ColorScheme
import androidx.compose.material3.darkColorScheme
import androidx.compose.material3.lightColorScheme
import androidx.compose.ui.graphics.Color
import kotlin.math.abs
import kotlin.math.max
import kotlin.math.min

// Each preset provides a seed color and light/dark primary colors
data class ThemePreset(
    val seed: Long,
    val lightPrimary: Color,
    val darkPrimary: Color,
)

val PresetThemeColors = mapOf(
    "pink" to ThemePreset(
        seed = 0xFFE91E8C,
        lightPrimary = Color(0xFFC2185B),
        darkPrimary = Color(0xFFFF80AB),
    ),
    "sakura" to ThemePreset(
        seed = 0xFFFFB4C8,
        lightPrimary = Color(0xFFE91E63),
        darkPrimary = Color(0xFFFFB4C8),
    ),
    "lavender" to ThemePreset(
        seed = 0xFF6D3BC0,
        lightPrimary = Color(0xFF6D3BC0),
        darkPrimary = Color(0xFFD3BBFF),
    ),
    "ocean" to ThemePreset(
        seed = 0xFF1565C0,
        lightPrimary = Color(0xFF1565C0),
        darkPrimary = Color(0xFF90CAF9),
    ),
    "forest" to ThemePreset(
        seed = 0xFF2E7D32,
        lightPrimary = Color(0xFF2E7D32),
        darkPrimary = Color(0xFFA5D6A7),
    ),
    "sunset" to ThemePreset(
        seed = 0xFFE65100,
        lightPrimary = Color(0xFFE65100),
        darkPrimary = Color(0xFFFFCC80),
    ),
    "rose" to ThemePreset(
        seed = 0xFFD81B60,
        lightPrimary = Color(0xFFAD1457),
        darkPrimary = Color(0xFFF48FB1),
    ),
    "sky" to ThemePreset(
        seed = 0xFF0277BD,
        lightPrimary = Color(0xFF0277BD),
        darkPrimary = Color(0xFF81D4FA),
    ),
    "mint" to ThemePreset(
        seed = 0xFF00695C,
        lightPrimary = Color(0xFF00695C),
        darkPrimary = Color(0xFF80CBC4),
    ),
)

val PresetColorLabels = mapOf(
    "pink" to "昔涟粉",
    "sakura" to "樱花粉",
    "lavender" to "薰衣草紫",
    "ocean" to "海洋蓝",
    "forest" to "森林绿",
    "sunset" to "日落橙",
    "rose" to "玫瑰红",
    "sky" to "天空蓝",
    "mint" to "薄荷青",
)

fun getPreset(key: String): ThemePreset = PresetThemeColors[key] ?: PresetThemeColors["pink"]!!

// --- Color derivation via HSL — generates cohesive MD3-like schemes ---

private data class HSL(val h: Float, val s: Float, val l: Float)

private fun Color.toHSL(): HSL {
    val r = red / 255f
    val g = green / 255f
    val b = blue / 255f
    val maxV = max(max(r, g), b)
    val minV = min(min(r, g), b)
    val delta = maxV - minV
    val l = (maxV + minV) / 2f
    val s = if (delta == 0f) 0f else delta / (1f - abs(2f * l - 1f))
    val h = when {
        delta == 0f -> 0f
        maxV == r -> 60f * (((g - b) / delta) % 6f)
        maxV == g -> 60f * (((b - r) / delta) + 2f)
        else -> 60f * (((r - g) / delta) + 4f)
    }
    return HSL(if (h < 0) h + 360f else h, s, l)
}

private fun hslToColor(h: Float, s: Float, l: Float): Color {
    val c = (1f - abs(2f * l - 1f)) * s
    val x = c * (1f - abs((h / 60f) % 2f - 1f))
    val m = l - c / 2f
    val (r, g, b) = when {
        h < 60f -> Triple(c, x, 0f)
        h < 120f -> Triple(x, c, 0f)
        h < 180f -> Triple(0f, c, x)
        h < 240f -> Triple(0f, x, c)
        h < 300f -> Triple(x, 0f, c)
        else -> Triple(c, 0f, x)
    }
    return Color((r + m).coerceIn(0f, 1f), (g + m).coerceIn(0f, 1f), (b + m).coerceIn(0f, 1f))
}

/**
 * Build a full light ColorScheme derived from a primary color.
 * All secondary/tertiary/container colors are computed from the primary
 * so focus rings, ripples, badges, and containers all match the theme.
 */
fun buildLightScheme(primary: Color): ColorScheme {
    val hsl = primary.toHSL()

    val primaryContainer = hslToColor(hsl.h, 0.3f, 0.90f)
    val onPrimaryContainer = hslToColor(hsl.h, 0.5f, 0.15f)

    // Secondary: similar hue, less saturated
    val secH = (hsl.h + 15f) % 360f
    val secondary = hslToColor(secH, 0.35f, 0.42f)
    val secondaryContainer = hslToColor(secH, 0.25f, 0.90f)
    val onSecondaryContainer = hslToColor(secH, 0.3f, 0.15f)

    // Tertiary: complementary hue shift
    val terH = (hsl.h + 60f) % 360f
    val tertiary = hslToColor(terH, 0.40f, 0.38f)
    val tertiaryContainer = hslToColor(terH, 0.30f, 0.90f)
    val onTertiaryContainer = hslToColor(terH, 0.35f, 0.15f)

    val onPrimary = Color.White
    val onSecondary = Color.White
    val onTertiary = Color.White
    val surfaceTint = primary

    return lightColorScheme(
        primary = primary,
        onPrimary = onPrimary,
        primaryContainer = primaryContainer,
        onPrimaryContainer = onPrimaryContainer,
        secondary = secondary,
        onSecondary = onSecondary,
        secondaryContainer = secondaryContainer,
        onSecondaryContainer = onSecondaryContainer,
        tertiary = tertiary,
        onTertiary = onTertiary,
        tertiaryContainer = tertiaryContainer,
        onTertiaryContainer = onTertiaryContainer,
        surfaceTint = surfaceTint,
    )
}

/**
 * Build a full dark ColorScheme derived from a primary color.
 */
fun buildDarkScheme(primary: Color): ColorScheme {
    val hsl = primary.toHSL()

    val primaryContainer = hslToColor(hsl.h, 0.40f, 0.22f)
    val onPrimaryContainer = hslToColor(hsl.h, 0.30f, 0.88f)
    val onPrimary = hslToColor(hsl.h, 0.5f, 0.10f)

    val secH = (hsl.h + 15f) % 360f
    val secondary = hslToColor(secH, 0.40f, 0.76f)
    val secondaryContainer = hslToColor(secH, 0.30f, 0.22f)
    val onSecondaryContainer = hslToColor(secH, 0.30f, 0.88f)
    val onSecondary = hslToColor(secH, 0.3f, 0.12f)

    val terH = (hsl.h + 60f) % 360f
    val tertiary = hslToColor(terH, 0.40f, 0.80f)
    val tertiaryContainer = hslToColor(terH, 0.30f, 0.22f)
    val onTertiaryContainer = hslToColor(terH, 0.30f, 0.88f)
    val onTertiary = hslToColor(terH, 0.3f, 0.12f)

    val surfaceTint = primary

    return darkColorScheme(
        primary = primary,
        onPrimary = onPrimary,
        primaryContainer = primaryContainer,
        onPrimaryContainer = onPrimaryContainer,
        secondary = secondary,
        onSecondary = onSecondary,
        secondaryContainer = secondaryContainer,
        onSecondaryContainer = onSecondaryContainer,
        tertiary = tertiary,
        onTertiary = onTertiary,
        tertiaryContainer = tertiaryContainer,
        onTertiaryContainer = onTertiaryContainer,
        surfaceTint = surfaceTint,
    )
}
