/*
 * Copyright 2026 Sergey S. Chernov real.sergeych@gmail.com
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *     http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 */

package net.sergeych.site

import net.sergeych.lyng.highlight.HighlightKind
import net.sergeych.lyng.highlight.HighlightSpan
import net.sergeych.lyng.highlight.SimpleLyngHighlighter
import net.sergeych.lyngweb.SiteHighlight
import kotlin.test.Test
import kotlin.test.assertContains
import kotlin.test.assertTrue

class HighlightSmokeTest {

    private fun spansToLabeled(text: String, spans: List<HighlightSpan>): List<Pair<String, HighlightKind>> =
        spans.map { text.substring(it.range.start, it.range.endExclusive) to it.kind }

    @Test
    fun highlightAssertEqualsSnippet() {
        val text = "assertEquals( [9,10], r.takeLast(2).toList() )"
        val spans = SimpleLyngHighlighter().highlight(text)
        val labeled = spansToLabeled(text, spans)

        // Basic sanity: identifier assertEquals present and not split
        assertTrue(labeled.any { it.first == "assertEquals" && it.second == HighlightKind.Identifier })
        // Basic numbers detection
        assertTrue(labeled.any { it.first == "9" && it.second == HighlightKind.Number })
        assertTrue(labeled.any { it.first == "10" && it.second == HighlightKind.Number })
        assertTrue(labeled.any { it.first == "2" && it.second == HighlightKind.Number })
    }

    @Test
    fun highlightMapLiteralHtml() {
        val text = """
            val base = { a: 1, b: }
            val m = { "a": 1, b: , ...base, }
        """.trimIndent()
        val html = SiteHighlight.renderHtml(text)
        // Curly braces and commas are punctuation
        assertContains(html, "<span class=\"hl-punc\">{</span>")
        assertContains(html, "<span class=\"hl-punc\">}</span>")
        assertTrue(html.contains("hl-punc") && html.contains(","), "comma should be punctuation")
        // Colon after key is punctuation
        assertContains(html, "<span class=\"hl-punc\">:</span>")
        // Spread operator present
        assertContains(html, "<span class=\"hl-op\">...</span>")
        // String key and identifier key appear
        assertContains(html, "<span class=\"hl-str\">&quot;a&quot;</span>")
        assertContains(html, "<span class=\"hl-id\">b</span>")
    }

    @Test
    fun renderHtmlContainsCorrectClasses() {
        val text = "assertEquals( [9,10], r.takeLast(2).toList() )"
        val html = SiteHighlight.renderHtml(text)
        // Ensure important parts are wrapped with expected classes
        // In the new renderer, call-sites are marked as functions (hl-fn). Accept either id or fn.
        assertTrue(
            html.contains("<span class=\"hl-id\">assertEquals</span>") ||
            html.contains("<span class=\"hl-fn\">assertEquals</span>"),
            "assertEquals should be highlighted as identifier or function call"
        )
        assertContains(html, "<span class=\"hl-num\">9</span>")
        assertContains(html, "<span class=\"hl-num\">10</span>")
        assertContains(html, "<span class=\"hl-num\">2</span>")
        // Punctuation and operators appear; allow either combined or separate, just ensure class exists
        assertTrue(html.contains("hl-punc"))
        assertTrue(html.contains("hl-op"))
    }

    @Test
    fun highlightNamedArgsAndMapSplat() {
        val text = """
            fun test(a,b,c,d) { [a,b,c,d] }
            val r = test("A?", c: "C!", ...Map("d" => "D!", "b" => "B!"))
        """.trimIndent()
        val spans = SimpleLyngHighlighter().highlight(text)
        val labeled = spansToLabeled(text, spans)
        // Ensure identifier for function name appears
        assertTrue(labeled.any { it.first == "test" && it.second == HighlightKind.Identifier })
        // Ensure colon for named argument is tokenized as punctuation
        assertTrue(labeled.any { it.first == ":" && it.second == HighlightKind.Punctuation })
        // Ensure ellipsis operator present
        assertTrue(labeled.any { it.first == "..." && it.second == HighlightKind.Operator })
        // Ensure Map identifier is present
        assertTrue(labeled.any { it.first == "Map" && it.second == HighlightKind.Identifier })
    }

    @Test
    fun highlightNamedArgsHtml() {
        val text = "val res = test( a: 1, b: 2 )"
        val html = SiteHighlight.renderHtml(text)
        // Expect a colon wrapped as punctuation span
        assertTrue(html.contains("<span class=\"hl-punc\">:</span>"))
    }
}
