package ru.forbion.f7cloud.feature.files

import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.text.BasicTextField
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.ArrowBack
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.SolidColor
import androidx.compose.ui.text.AnnotatedString
import androidx.compose.ui.text.SpanStyle
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.buildAnnotatedString
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.font.FontStyle
import androidx.compose.ui.text.withStyle
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import ru.forbion.f7cloud.core.auth.AuthSession
import ru.forbion.f7cloud.core.designsystem.F7Colors
import ru.forbion.f7cloud.core.designsystem.f7SafeTopInsets

/**
 * Нативный редактор markdown/текста: качает содержимое по WebDAV (мгновенно), правка в
 * TextField, предпросмотр с базовым рендером, сохранение по WebDAV PUT. Заменяет тяжёлый
 * веб-редактор Text (который «вечно грузился», т.к. тянул весь Files UI).
 */
@Composable
fun MarkdownEditorScreen(
    session: AuthSession,
    doc: MarkdownDoc,
    onClose: () -> Unit,
    repository: MarkdownRepository = remember { MarkdownRepository() },
) {
    var text by remember(doc.relativePath) { mutableStateOf("") }
    var loading by remember(doc.relativePath) { mutableStateOf(true) }
    var saving by remember { mutableStateOf(false) }
    var error by remember { mutableStateOf<String?>(null) }
    var preview by remember { mutableStateOf(false) }
    var dirty by remember(doc.relativePath) { mutableStateOf(false) }
    val scope = rememberCoroutineScope()
    val isMd = doc.name.substringAfterLast('.', "").lowercase() in setOf("md", "markdown")

    LaunchedEffect(doc.relativePath) {
        loading = true
        error = null
        runCatching { withContext(Dispatchers.IO) { repository.load(session, doc.relativePath) } }
            .onSuccess { text = it; loading = false }
            .onFailure { error = it.message ?: "Ошибка загрузки"; loading = false }
    }

    Column(
        modifier = Modifier
            .fillMaxSize()
            .background(F7Colors.Background)
            .f7SafeTopInsets(),
    ) {
        // Шапка: назад, имя, предпросмотр (для md), сохранить
        Row(
            modifier = Modifier
                .fillMaxWidth()
                .padding(horizontal = 12.dp, vertical = 10.dp),
            verticalAlignment = Alignment.CenterVertically,
            horizontalArrangement = Arrangement.spacedBy(8.dp),
        ) {
            Icon(
                Icons.AutoMirrored.Filled.ArrowBack,
                contentDescription = "Назад",
                tint = F7Colors.TextPrimary,
                modifier = Modifier.size(24.dp).clickable(onClick = onClose),
            )
            Text(
                doc.name,
                modifier = Modifier.weight(1f),
                style = MaterialTheme.typography.titleMedium,
                fontWeight = FontWeight.SemiBold,
                color = F7Colors.TextPrimary,
                maxLines = 1,
            )
            if (isMd) {
                Box(
                    modifier = Modifier
                        .clip(RoundedCornerShape(100.dp))
                        .background(if (preview) F7Colors.PrimaryLight else F7Colors.SurfaceMuted)
                        .clickable { preview = !preview }
                        .padding(horizontal = 12.dp, vertical = 6.dp),
                ) {
                    Text(
                        if (preview) "Правка" else "Просмотр",
                        style = MaterialTheme.typography.bodyMedium,
                        color = F7Colors.TextPrimary,
                    )
                }
            }
            Box(
                modifier = Modifier
                    .clip(RoundedCornerShape(100.dp))
                    .background(if (dirty && !saving) F7Colors.Primary else F7Colors.SurfaceMuted)
                    .clickable(enabled = dirty && !saving) {
                        saving = true
                        error = null
                        scope.launch {
                            runCatching {
                                withContext(Dispatchers.IO) { repository.save(session, doc.relativePath, text) }
                            }.onSuccess { saving = false; dirty = false }
                                .onFailure { error = it.message ?: "Ошибка сохранения"; saving = false }
                        }
                    }
                    .padding(horizontal = 14.dp, vertical = 6.dp),
            ) {
                Text(
                    if (saving) "…" else "Сохранить",
                    style = MaterialTheme.typography.bodyMedium,
                    fontWeight = FontWeight.Medium,
                    color = if (dirty && !saving) androidx.compose.ui.graphics.Color.White else F7Colors.TextSecondary,
                )
            }
        }
        error?.let {
            Text(it, color = F7Colors.Error, modifier = Modifier.padding(horizontal = 16.dp, vertical = 4.dp))
        }

        when {
            loading -> Box(Modifier.fillMaxSize(), contentAlignment = Alignment.Center) {
                CircularProgressIndicator(color = F7Colors.Primary)
            }
            preview && isMd -> {
                Column(
                    modifier = Modifier
                        .fillMaxSize()
                        .verticalScroll(rememberScrollState())
                        .padding(16.dp),
                ) {
                    Text(renderMarkdown(text), style = MaterialTheme.typography.bodyLarge, color = F7Colors.TextPrimary)
                }
            }
            else -> {
                BasicTextField(
                    value = text,
                    onValueChange = { text = it; dirty = true },
                    modifier = Modifier
                        .fillMaxSize()
                        .padding(16.dp),
                    textStyle = TextStyle(
                        fontSize = 15.sp,
                        lineHeight = 22.sp,
                        color = F7Colors.TextPrimary,
                        fontFamily = if (isMd) FontFamily.Monospace else FontFamily.Default,
                    ),
                    cursorBrush = SolidColor(F7Colors.Primary),
                )
            }
        }
    }
}

/** Лёгкий рендер markdown → AnnotatedString: заголовки, жирный/курсив, списки, код, цитаты. */
private fun renderMarkdown(src: String): AnnotatedString = buildAnnotatedString {
    src.lineSequence().forEachIndexed { index, raw ->
        if (index > 0) append("\n")
        val line = raw.trimEnd()
        when {
            line.startsWith("### ") -> withStyle(SpanStyle(fontSize = 16.sp, fontWeight = FontWeight.Bold)) {
                append(line.removePrefix("### "))
            }
            line.startsWith("## ") -> withStyle(SpanStyle(fontSize = 18.sp, fontWeight = FontWeight.Bold)) {
                append(line.removePrefix("## "))
            }
            line.startsWith("# ") -> withStyle(SpanStyle(fontSize = 22.sp, fontWeight = FontWeight.Bold)) {
                append(line.removePrefix("# "))
            }
            line.startsWith("> ") -> withStyle(
                SpanStyle(fontStyle = FontStyle.Italic, color = androidx.compose.ui.graphics.Color(0xFF808080)),
            ) { append(line.removePrefix("> ")) }
            line.startsWith("- ") || line.startsWith("* ") -> {
                append("•  ")
                appendInline(line.drop(2))
            }
            line.matches(Regex("^\\d+\\. .*")) -> appendInline(line)
            line.startsWith("```") -> withStyle(SpanStyle(fontFamily = FontFamily.Monospace)) { append(line) }
            else -> appendInline(line)
        }
    }
}

/** Инлайн-разметка: **жирный**, *курсив*, `код`. */
private fun androidx.compose.ui.text.AnnotatedString.Builder.appendInline(text: String) {
    var i = 0
    while (i < text.length) {
        when {
            text.startsWith("**", i) -> {
                val end = text.indexOf("**", i + 2)
                if (end > 0) {
                    withStyle(SpanStyle(fontWeight = FontWeight.Bold)) { append(text.substring(i + 2, end)) }
                    i = end + 2
                } else { append(text[i]); i++ }
            }
            text[i] == '*' -> {
                val end = text.indexOf('*', i + 1)
                if (end > 0) {
                    withStyle(SpanStyle(fontStyle = FontStyle.Italic)) { append(text.substring(i + 1, end)) }
                    i = end + 1
                } else { append(text[i]); i++ }
            }
            text[i] == '`' -> {
                val end = text.indexOf('`', i + 1)
                if (end > 0) {
                    withStyle(SpanStyle(fontFamily = FontFamily.Monospace)) { append(text.substring(i + 1, end)) }
                    i = end + 1
                } else { append(text[i]); i++ }
            }
            else -> { append(text[i]); i++ }
        }
    }
}
