package com.example.notesai.util

import androidx.compose.foundation.background
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.*
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.*
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.font.FontStyle
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextDecoration
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.example.notesai.util.AppColors
import com.example.notesai.util.Constants

@Composable
fun MarkdownText(
    markdown: String,
    modifier: Modifier = Modifier
) {
    Column(
        modifier = modifier,
        verticalArrangement = Arrangement.spacedBy(8.dp)
    ) {
        parseMarkdown(markdown).forEach { block ->
            when (block) {
                is MarkdownBlock.Paragraph -> {
                    Text(
                        text = buildAnnotatedString {
                            appendInlineMarkdown(block.content)
                        },
                        style = MaterialTheme.typography.bodyMedium,
                        color = AppColors.OnSurface,
                        lineHeight = 24.sp
                    )
                }
                is MarkdownBlock.Header -> {
                    Spacer(modifier = Modifier.height(4.dp))
                    Text(
                        text = block.content,
                        style = when (block.level) {
                            1 -> MaterialTheme.typography.headlineLarge
                            2 -> MaterialTheme.typography.headlineMedium
                            3 -> MaterialTheme.typography.headlineSmall
                            else -> MaterialTheme.typography.titleLarge
                        },
                        color = AppColors.OnBackground,
                        fontWeight = FontWeight.Bold
                    )
                    Spacer(modifier = Modifier.height(4.dp))
                }
                is MarkdownBlock.CodeBlock -> {
                    Surface(
                        modifier = Modifier.fillMaxWidth(),
                        color = AppColors.SurfaceVariant,
                        shape = RoundedCornerShape(Constants.Radius.Medium.dp)
                    ) {
                        Text(
                            text = block.content,
                            modifier = Modifier.padding(12.dp),
                            fontFamily = FontFamily.Monospace,
                            style = MaterialTheme.typography.bodySmall,
                            color = AppColors.OnSurface,
                            fontSize = 13.sp
                        )
                    }
                }
                is MarkdownBlock.ListItem -> {
                    Row(
                        modifier = Modifier.fillMaxWidth(),
                        horizontalArrangement = Arrangement.spacedBy(8.dp)
                    ) {
                        Text(
                            text = if (block.isOrdered) "${block.number}." else "•",
                            color = AppColors.Primary,
                            style = MaterialTheme.typography.bodyMedium,
                            modifier = Modifier.width(20.dp)
                        )
                        Text(
                            text = buildAnnotatedString {
                                appendInlineMarkdown(block.content)
                            },
                            style = MaterialTheme.typography.bodyMedium,
                            color = AppColors.OnSurface,
                            modifier = Modifier.weight(1f)
                        )
                    }
                }
                is MarkdownBlock.Quote -> {
                    Surface(
                        modifier = Modifier.fillMaxWidth(),
                        color = AppColors.Primary.copy(alpha = 0.1f),
                        shape = RoundedCornerShape(Constants.Radius.Medium.dp)
                    ) {
                        Row {
                            Spacer(
                                modifier = Modifier
                                    .width(4.dp)
                                    .fillMaxHeight()
                                    .background(AppColors.Primary)
                            )
                            Text(
                                text = buildAnnotatedString {
                                    appendInlineMarkdown(block.content)
                                },
                                modifier = Modifier.padding(12.dp),
                                style = MaterialTheme.typography.bodyMedium,
                                color = AppColors.OnSurface,
                                fontStyle = FontStyle.Italic
                            )
                        }
                    }
                }
            }
        }
    }
}

// Markdown Block Types
sealed class MarkdownBlock {
    data class Paragraph(val content: String) : MarkdownBlock()
    data class Header(val level: Int, val content: String) : MarkdownBlock()
    data class CodeBlock(val content: String, val language: String? = null) : MarkdownBlock()
    data class ListItem(val content: String, val isOrdered: Boolean, val number: Int = 0) : MarkdownBlock()
    data class Quote(val content: String) : MarkdownBlock()
}

// Parse markdown into blocks
fun parseMarkdown(text: String): List<MarkdownBlock> {
    val blocks = mutableListOf<MarkdownBlock>()
    val lines = text.lines()
    var i = 0

    while (i < lines.size) {
        val line = lines[i]

        when {
            // Code block
            line.trimStart().startsWith("```") -> {
                val language = line.trimStart().removePrefix("```").trim()
                val codeLines = mutableListOf<String>()
                i++
                while (i < lines.size && !lines[i].trimStart().startsWith("```")) {
                    codeLines.add(lines[i])
                    i++
                }
                blocks.add(MarkdownBlock.CodeBlock(codeLines.joinToString("\n"), language.ifEmpty { null }))
                i++
            }
            // Header
            line.trimStart().startsWith("#") -> {
                val level = line.takeWhile { it == '#' }.length
                val content = line.removePrefix("#".repeat(level)).trim()
                blocks.add(MarkdownBlock.Header(level, content))
                i++
            }
            // Quote
            line.trimStart().startsWith(">") -> {
                val content = line.trimStart().removePrefix(">").trim()
                blocks.add(MarkdownBlock.Quote(content))
                i++
            }
            // Unordered list
            line.trimStart().matches(Regex("^[-*+]\\s+.*")) -> {
                val content = line.trimStart().replaceFirst(Regex("^[-*+]\\s+"), "")
                blocks.add(MarkdownBlock.ListItem(content, false))
                i++
            }
            // Ordered list
            line.trimStart().matches(Regex("^\\d+\\.\\s+.*")) -> {
                val number = line.trimStart().takeWhile { it.isDigit() }.toIntOrNull() ?: 1
                val content = line.trimStart().replaceFirst(Regex("^\\d+\\.\\s+"), "")
                blocks.add(MarkdownBlock.ListItem(content, true, number))
                i++
            }
            // Empty line - skip
            line.isBlank() -> {
                i++
            }
            // Paragraph
            else -> {
                val paragraphLines = mutableListOf<String>()
                while (i < lines.size && lines[i].isNotBlank() &&
                    !lines[i].trimStart().startsWith("#") &&
                    !lines[i].trimStart().startsWith(">") &&
                    !lines[i].trimStart().startsWith("```") &&
                    !lines[i].trimStart().matches(Regex("^[-*+]\\s+.*")) &&
                    !lines[i].trimStart().matches(Regex("^\\d+\\.\\s+.*"))) {
                    paragraphLines.add(lines[i])
                    i++
                }
                if (paragraphLines.isNotEmpty()) {
                    blocks.add(MarkdownBlock.Paragraph(paragraphLines.joinToString(" ")))
                }
            }
        }
    }

    return blocks
}

// Parse inline markdown (bold, italic, code, links)
fun AnnotatedString.Builder.appendInlineMarkdown(text: String) {
    var currentIndex = 0
    val inlinePatterns = listOf(
        // Bold with **
        Regex("""\*\*(.+?)\*\*""") to { content: String ->
            withStyle(SpanStyle(fontWeight = FontWeight.Bold)) {
                append(content)
            }
        },
        // Bold with __
        Regex("""__(.+?)__""") to { content: String ->
            withStyle(SpanStyle(fontWeight = FontWeight.Bold)) {
                append(content)
            }
        },
        // Italic with *
        Regex("""\*(.+?)\*""") to { content: String ->
            withStyle(SpanStyle(fontStyle = FontStyle.Italic)) {
                append(content)
            }
        },
        // Italic with _
        Regex("""_(.+?)_""") to { content: String ->
            withStyle(SpanStyle(fontStyle = FontStyle.Italic)) {
                append(content)
            }
        },
        // Inline code
        Regex("""`(.+?)`""") to { content: String ->
            withStyle(
                SpanStyle(
                    fontFamily = FontFamily.Monospace,
                    background = Color(0xFF1E1E1E),
                    color = Color(0xFFE5E5E5)
                )
            ) {
                append(" $content ")
            }
        },
        // Links [text](url)
        Regex("""\[(.+?)]\((.+?)\)""") to { content: String ->
            withStyle(
                SpanStyle(
                    color = Color(0xFF3B82F6),
                    textDecoration = TextDecoration.Underline
                )
            ) {
                append(content)
            }
        }
    )

    var remainingText = text
    val matches = mutableListOf<Triple<Int, Int, (String) -> Unit>>()

    // Find all matches
    inlinePatterns.forEach { (regex, styleApplier) ->
        regex.findAll(remainingText).forEach { match ->
            val content = match.groupValues[1]
            matches.add(Triple(match.range.first, match.range.last + 1) { styleApplier(content) })
        }
    }

    // Sort matches by start position
    val sortedMatches = matches.sortedBy { it.first }

    // Apply styles
    var lastIndex = 0
    sortedMatches.forEach { (start, end, applier) ->
        if (start >= lastIndex) {
            // Append text before match
            append(remainingText.substring(lastIndex, start))
            // Apply style
            applier("")
            lastIndex = end
        }
    }

    // Append remaining text
    if (lastIndex < remainingText.length) {
        append(remainingText.substring(lastIndex))
    }
}