package com.tt.honeyDue.ui.theme

import androidx.compose.ui.graphics.Color
import kotlin.test.Test
import kotlin.test.assertEquals
import kotlin.test.assertNotNull
import kotlin.test.assertTrue

/**
 * P1 Stream A — Design-token parity tests.
 *
 * Source of truth is the iOS app. Values captured in
 * `docs/ios-parity/colors.json` (198 hex values: 11 themes x 9 fields x 2 modes).
 *
 * Because common source sets cannot read files at test runtime in KMP without
 * extra dependencies, the JSON ground truth is embedded below as a Kotlin
 * constant and parsed with a tiny hand-rolled parser tailored to the schema.
 */
class ThemeColorsTest {

    /**
     * Verbatim copy of docs/ios-parity/colors.json.
     * Keep in sync whenever the iOS palette changes.
     */
    private val iosColorsJson = """
{
  "themes": {
    "Default": {
      "Primary":             { "light": "#007AFF",   "dark": "#0A84FF" },
      "Secondary":           { "light": "#5AC8FA",   "dark": "#64D2FF" },
      "Accent":              { "light": "#FF9500",   "dark": "#FF9F0A" },
      "Error":               { "light": "#FF3B30",   "dark": "#FF453A" },
      "BackgroundPrimary":   { "light": "#FFFFFF",   "dark": "#1C1C1C" },
      "BackgroundSecondary": { "light": "#F2F7F7",   "dark": "#2C2C2C" },
      "TextPrimary":         { "light": "#111111",   "dark": "#FFFFFF" },
      "TextSecondary":       { "light": "#3D3D3D99", "dark": "#EBEBEB99" },
      "TextOnPrimary":       { "light": "#FFFFFF",   "dark": "#FFFFFF" }
    },
    "Crimson": {
      "Primary":             { "light": "#B51E28", "dark": "#FF827D" },
      "Secondary":           { "light": "#992E38", "dark": "#FA9994" },
      "Accent":              { "light": "#E36100", "dark": "#FFB56B" },
      "Error":               { "light": "#DD1C1A", "dark": "#FF5344" },
      "BackgroundPrimary":   { "light": "#F6EEEC", "dark": "#1B1216" },
      "BackgroundSecondary": { "light": "#DECFCC", "dark": "#412F39" },
      "TextPrimary":         { "light": "#111111", "dark": "#F5F5F5" },
      "TextSecondary":       { "light": "#444444", "dark": "#C7C7C7" },
      "TextOnPrimary":       { "light": "#FFFFFF", "dark": "#FFFFFF" }
    },
    "Desert": {
      "Primary":             { "light": "#B0614A", "dark": "#F2B594" },
      "Secondary":           { "light": "#9E7D61", "dark": "#EBD1B0" },
      "Accent":              { "light": "#D1942E", "dark": "#FFD96B" },
      "Error":               { "light": "#DD1C1A", "dark": "#FF5344" },
      "BackgroundPrimary":   { "light": "#F6F1EB", "dark": "#201C17" },
      "BackgroundSecondary": { "light": "#E6D9C7", "dark": "#4A4138" },
      "TextPrimary":         { "light": "#111111", "dark": "#F5F5F5" },
      "TextSecondary":       { "light": "#444444", "dark": "#C7C7C7" },
      "TextOnPrimary":       { "light": "#FFFFFF", "dark": "#FFFFFF" }
    },
    "Forest": {
      "Primary":             { "light": "#2D5016", "dark": "#94C76B" },
      "Secondary":           { "light": "#6B8E23", "dark": "#B0D182" },
      "Accent":              { "light": "#FFD700", "dark": "#FFD700" },
      "Error":               { "light": "#DD1C1A", "dark": "#FF5344" },
      "BackgroundPrimary":   { "light": "#ECEFE3", "dark": "#191E18" },
      "BackgroundSecondary": { "light": "#C1C9AE", "dark": "#384436" },
      "TextPrimary":         { "light": "#111111", "dark": "#F5F5F5" },
      "TextSecondary":       { "light": "#444444", "dark": "#C7C7C7" },
      "TextOnPrimary":       { "light": "#FFFFFF", "dark": "#FFFFFF" }
    },
    "Lavender": {
      "Primary":             { "light": "#6B418B", "dark": "#D1B0E3" },
      "Secondary":           { "light": "#8B61B0", "dark": "#DEBFEB" },
      "Accent":              { "light": "#E34A82", "dark": "#FF9EC7" },
      "Error":               { "light": "#DD1C1A", "dark": "#FF5344" },
      "BackgroundPrimary":   { "light": "#F2F0F5", "dark": "#18141E" },
      "BackgroundSecondary": { "light": "#D9D1E0", "dark": "#393142" },
      "TextPrimary":         { "light": "#111111", "dark": "#F5F5F5" },
      "TextSecondary":       { "light": "#444444", "dark": "#C7C7C7" },
      "TextOnPrimary":       { "light": "#FFFFFF", "dark": "#FFFFFF" }
    },
    "Midnight": {
      "Primary":             { "light": "#1E4A94", "dark": "#82B5EB" },
      "Secondary":           { "light": "#2E61B0", "dark": "#94C7F2" },
      "Accent":              { "light": "#4A94E3", "dark": "#9ED9FF" },
      "Error":               { "light": "#DD1C1A", "dark": "#FF5344" },
      "BackgroundPrimary":   { "light": "#EEF1F7", "dark": "#121720" },
      "BackgroundSecondary": { "light": "#CCD6E3", "dark": "#303849" },
      "TextPrimary":         { "light": "#111111", "dark": "#F5F5F5" },
      "TextSecondary":       { "light": "#444444", "dark": "#C7C7C7" },
      "TextOnPrimary":       { "light": "#FFFFFF", "dark": "#FFFFFF" }
    },
    "Mint": {
      "Primary":             { "light": "#38B094", "dark": "#94F2D9" },
      "Secondary":           { "light": "#61C7B0", "dark": "#BFFAEB" },
      "Accent":              { "light": "#2E9EB0", "dark": "#6BEBF2" },
      "Error":               { "light": "#DD1C1A", "dark": "#FF5344" },
      "BackgroundPrimary":   { "light": "#EEF6F1", "dark": "#172020" },
      "BackgroundSecondary": { "light": "#D1E3D9", "dark": "#384A4A" },
      "TextPrimary":         { "light": "#111111", "dark": "#F5F5F5" },
      "TextSecondary":       { "light": "#444444", "dark": "#C7C7C7" },
      "TextOnPrimary":       { "light": "#FFFFFF", "dark": "#FFFFFF" }
    },
    "Monochrome": {
      "Primary":             { "light": "#333333", "dark": "#E6E6E6" },
      "Secondary":           { "light": "#666666", "dark": "#BFBFBF" },
      "Accent":              { "light": "#999999", "dark": "#D1D1D1" },
      "Error":               { "light": "#DD1C1A", "dark": "#FF5344" },
      "BackgroundPrimary":   { "light": "#F1F1F1", "dark": "#171717" },
      "BackgroundSecondary": { "light": "#D5D5D5", "dark": "#3C3C3C" },
      "TextPrimary":         { "light": "#111111", "dark": "#F5F5F5" },
      "TextSecondary":       { "light": "#444444", "dark": "#C7C7C7" },
      "TextOnPrimary":       { "light": "#FFFFFF", "dark": "#FFFFFF" }
    },
    "Ocean": {
      "Primary":             { "light": "#006B8F", "dark": "#4AB5D1" },
      "Secondary":           { "light": "#008B8B", "dark": "#61D1C7" },
      "Accent":              { "light": "#FF7F50", "dark": "#FF7F50" },
      "Error":               { "light": "#DD1C1A", "dark": "#FF5344" },
      "BackgroundPrimary":   { "light": "#E5ECF2", "dark": "#171B23" },
      "BackgroundSecondary": { "light": "#BDCBD6", "dark": "#323B4C" },
      "TextPrimary":         { "light": "#111111", "dark": "#F5F5F5" },
      "TextSecondary":       { "light": "#444444", "dark": "#C7C7C7" },
      "TextOnPrimary":       { "light": "#FFFFFF", "dark": "#FFFFFF" }
    },
    "Sunset": {
      "Primary":             { "light": "#FF4500", "dark": "#FF9E61" },
      "Secondary":           { "light": "#FF6347", "dark": "#FFAD7D" },
      "Accent":              { "light": "#FFD700", "dark": "#FFD700" },
      "Error":               { "light": "#DD1C1A", "dark": "#FF5344" },
      "BackgroundPrimary":   { "light": "#F7F1E8", "dark": "#211914" },
      "BackgroundSecondary": { "light": "#DCD0BB", "dark": "#433329" },
      "TextPrimary":         { "light": "#111111", "dark": "#F5F5F5" },
      "TextSecondary":       { "light": "#444444", "dark": "#C7C7C7" },
      "TextOnPrimary":       { "light": "#FFFFFF", "dark": "#FFFFFF" }
    },
    "Teal": {
      "Primary":             { "light": "#07A0C3", "dark": "#61CCE3" },
      "Secondary":           { "light": "#0055A5", "dark": "#61A6D9" },
      "Accent":              { "light": "#F0C808", "dark": "#F0C808" },
      "Error":               { "light": "#DD1C1A", "dark": "#FF5344" },
      "BackgroundPrimary":   { "light": "#FFF1D0", "dark": "#0A1929" },
      "BackgroundSecondary": { "light": "#FFFFFF", "dark": "#1A2F3F" },
      "TextPrimary":         { "light": "#111111", "dark": "#F5F5F5" },
      "TextSecondary":       { "light": "#444444", "dark": "#C7C7C7" },
      "TextOnPrimary":       { "light": "#FFFFFF", "dark": "#FFFFFF" }
    }
  }
}
""".trimIndent()

    /**
     * iOS theme name ("Default") → Android theme id ("default").
     */
    private val iosToAndroidId = mapOf(
        "Default" to "default",
        "Teal" to "teal",
        "Ocean" to "ocean",
        "Forest" to "forest",
        "Sunset" to "sunset",
        "Monochrome" to "monochrome",
        "Lavender" to "lavender",
        "Crimson" to "crimson",
        "Midnight" to "midnight",
        "Desert" to "desert",
        "Mint" to "mint",
    )

    /**
     * Field name in JSON → function extracting the corresponding Android
     * Color for a given mode ("light" or "dark").
     */
    private val fieldAccessors:
        Map<String, (ThemeColors, String) -> Color> = mapOf(
        "Primary" to { t, m -> if (m == "light") t.lightPrimary else t.darkPrimary },
        "Secondary" to { t, m -> if (m == "light") t.lightSecondary else t.darkSecondary },
        "Accent" to { t, m -> if (m == "light") t.lightAccent else t.darkAccent },
        "Error" to { t, m -> if (m == "light") t.lightError else t.darkError },
        "BackgroundPrimary" to { t, m ->
            if (m == "light") t.lightBackgroundPrimary else t.darkBackgroundPrimary
        },
        "BackgroundSecondary" to { t, m ->
            if (m == "light") t.lightBackgroundSecondary else t.darkBackgroundSecondary
        },
        "TextPrimary" to { t, m ->
            if (m == "light") t.lightTextPrimary else t.darkTextPrimary
        },
        "TextSecondary" to { t, m ->
            if (m == "light") t.lightTextSecondary else t.darkTextSecondary
        },
        "TextOnPrimary" to { t, m ->
            if (m == "light") t.lightTextOnPrimary else t.darkTextOnPrimary
        },
    )

    // ---------------------------------------------------------------------
    // Parser — tiny JSON reader tuned to the fixed schema above
    // ---------------------------------------------------------------------

    /**
     * Parse the colors.json body into a nested map:
     * themeName → fieldName → mode → hex string.
     */
    private fun parseIosColors(json: String): Map<String, Map<String, Map<String, String>>> {
        val hexRegex = Regex("\"#([0-9A-Fa-f]{6}|[0-9A-Fa-f]{8})\"")
        val themeBlockRegex = Regex(
            "\"([A-Za-z]+)\"\\s*:\\s*\\{([^{}]*(?:\\{[^{}]*\\}[^{}]*)*)\\}"
        )
        // Find the "themes" object
        val themesStart = json.indexOf("\"themes\"")
        require(themesStart >= 0) { "colors.json must contain a `themes` key" }
        val openBrace = json.indexOf('{', themesStart + "\"themes\"".length + 1)
        // Walk to matching close brace
        var depth = 0
        var endIdx = -1
        for (i in openBrace until json.length) {
            when (json[i]) {
                '{' -> depth++
                '}' -> {
                    depth--
                    if (depth == 0) { endIdx = i; break }
                }
            }
        }
        require(endIdx > openBrace) { "unterminated `themes` block" }
        val themesBody = json.substring(openBrace + 1, endIdx)

        val result = mutableMapOf<String, MutableMap<String, MutableMap<String, String>>>()

        // Iterate top-level theme entries
        var cursor = 0
        while (cursor < themesBody.length) {
            val nameMatch = Regex("\"([A-Za-z]+)\"\\s*:\\s*\\{")
                .find(themesBody, cursor) ?: break
            val themeName = nameMatch.groupValues[1]
            val themeOpen = nameMatch.range.last
            // find matching close brace for this theme
            var d = 0
            var themeEnd = -1
            for (i in themeOpen until themesBody.length) {
                when (themesBody[i]) {
                    '{' -> d++
                    '}' -> { d--; if (d == 0) { themeEnd = i; break } }
                }
            }
            require(themeEnd > themeOpen) { "unterminated theme block for $themeName" }
            val themeBody = themesBody.substring(themeOpen + 1, themeEnd)

            // Within themeBody, each field is `"Name": { "light": "#...", "dark": "#..." }`
            val fieldRegex = Regex(
                "\"([A-Za-z]+)\"\\s*:\\s*\\{\\s*\"light\"\\s*:\\s*\"(#[0-9A-Fa-f]{6,8})\"\\s*,\\s*\"dark\"\\s*:\\s*\"(#[0-9A-Fa-f]{6,8})\"\\s*\\}"
            )
            val fieldsMap = mutableMapOf<String, MutableMap<String, String>>()
            fieldRegex.findAll(themeBody).forEach { m ->
                val (fieldName, light, dark) = m.destructured
                fieldsMap[fieldName] = mutableMapOf("light" to light, "dark" to dark)
            }
            result[themeName] = fieldsMap

            cursor = themeEnd + 1
        }

        return result
    }

    /**
     * Convert a `#RRGGBB` or `#RRGGBBAA` string into a Compose [Color]
     * using the same packing scheme the implementation uses.
     *
     * - 6 hex digits → opaque (alpha = 0xFF).
     * - 8 hex digits (iOS `#RRGGBBAA`) → alpha is the trailing pair.
     *   Compose packs as 0xAARRGGBB.
     */
    private fun hexToColor(hex: String): Color {
        val clean = hex.removePrefix("#")
        return when (clean.length) {
            6 -> Color(0xFF000000 or clean.toLong(16))
            8 -> {
                val r = clean.substring(0, 2).toInt(16)
                val g = clean.substring(2, 4).toInt(16)
                val b = clean.substring(4, 6).toInt(16)
                val a = clean.substring(6, 8).toInt(16)
                Color(red = r, green = g, blue = b, alpha = a)
            }
            else -> error("Invalid hex: $hex")
        }
    }

    // ---------------------------------------------------------------------
    // Tests
    // ---------------------------------------------------------------------

    @Test
    fun allElevenThemesPresentWithStableIds() {
        val expectedIds = listOf(
            "default", "teal", "ocean", "forest", "sunset", "monochrome",
            "lavender", "crimson", "midnight", "desert", "mint"
        )
        val actualIds = AppThemes.allThemes.map { it.id }
        assertEquals(
            expectedIds.sorted(),
            actualIds.sorted(),
            "AppThemes.allThemes must expose exactly the 11 iOS theme ids"
        )
        assertEquals(
            11, AppThemes.allThemes.size,
            "AppThemes.allThemes.size must be 11"
        )

        // getThemeById works for every id
        expectedIds.forEach { id ->
            val t = AppThemes.getThemeById(id)
            assertEquals(id, t.id, "getThemeById('$id') must return theme with matching id")
        }
    }

    @Test
    fun everyColorMatchesIosGroundTruth() {
        val parsed = parseIosColors(iosColorsJson)
        assertEquals(
            11, parsed.size,
            "Parser must recognise all 11 iOS themes"
        )

        val mismatches = mutableListOf<String>()
        var assertions = 0

        parsed.forEach { (iosName, fields) ->
            val androidId = iosToAndroidId[iosName]
                ?: error("Unknown iOS theme name: $iosName")
            val androidTheme = AppThemes.allThemes.find { it.id == androidId }
            assertNotNull(androidTheme, "Android theme '$androidId' missing")

            fields.forEach { (fieldName, modes) ->
                val accessor = fieldAccessors[fieldName]
                    ?: error("Unknown field: $fieldName")
                listOf("light", "dark").forEach { mode ->
                    val expectedHex = modes[mode]
                        ?: error("Missing $mode for $iosName.$fieldName")
                    val expectedColor = hexToColor(expectedHex)
                    val actualColor = accessor(androidTheme, mode)
                    assertions++
                    if (expectedColor.value != actualColor.value) {
                        mismatches += "$iosName.$fieldName.$mode expected=$expectedHex " +
                            "(0x${expectedColor.value.toString(16)}) " +
                            "actual=0x${actualColor.value.toString(16)}"
                    }
                }
            }
        }

        assertTrue(
            assertions >= 198,
            "Expected at least 198 color assertions, got $assertions"
        )
        assertTrue(
            mismatches.isEmpty(),
            "Android ThemeColors do not match iOS ground truth:\n" +
                mismatches.joinToString("\n")
        )
    }

    @Test
    fun textSecondaryAlphaPreservedForDefaultTheme() {
        // iOS encodes TextSecondary with a 0x99 alpha channel on Default.
        // Verify the alpha survives the conversion round-trip.
        val expectedLight = hexToColor("#3D3D3D99")
        val expectedDark = hexToColor("#EBEBEB99")
        assertEquals(
            expectedLight.value, AppThemes.Default.lightTextSecondary.value,
            "Default.lightTextSecondary must retain #3D3D3D99 alpha"
        )
        assertEquals(
            expectedDark.value, AppThemes.Default.darkTextSecondary.value,
            "Default.darkTextSecondary must retain #EBEBEB99 alpha"
        )
    }

    @Test
    fun hexConverterHandlesBothLengths() {
        // sanity check for the test's own helper
        val opaque = hexToColor("#FF0000")
        assertEquals(0xFFFF0000.toInt(), opaque.value.shr(32).toInt())

        val withAlpha = hexToColor("#FF000080")
        // alpha = 0x80
        val alphaByte = (withAlpha.value shr 56).toInt() and 0xFF
        assertEquals(0x80, alphaByte, "8-digit hex must set alpha from trailing pair")
    }
}
