package mg.dot.feufaro

import SharedScreenModel
import androidx.compose.foundation.*
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.text.BasicTextField
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.ArrowBack
import androidx.compose.material.icons.automirrored.filled.ArrowForward
import androidx.compose.material.icons.filled.*
import androidx.compose.material.icons.sharp.Delete
import androidx.compose.material3.*
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.SolidColor
import androidx.compose.ui.layout.onGloballyPositioned
import androidx.compose.ui.layout.positionInParent
import androidx.compose.ui.platform.LocalSoftwareKeyboardController
import androidx.compose.ui.text.TextRange
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontFamily
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.text.input.TextFieldValue
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.*
import androidx.compose.ui.window.Popup
import androidx.compose.ui.window.PopupProperties
import mg.dot.feufaro.solfa.MarkerPopup
import mg.dot.feufaro.solfa.Solfa
import mg.dot.feufaro.solfa.TUOEditState
import mg.dot.feufaro.solfa.TimeUnitObject
import mg.dot.feufaro.ui.LocalSolfaKeyboardState

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun TUODetailDialog(
    editState: TUOEditState,
    tuo: TimeUnitObject,
    currentStanza: Int,
    menuPosition: IntOffset,
    globalIndex: Int,
    isEditable: Boolean,
    canAdd: Boolean,
    sharedScreenModel: SharedScreenModel,
    anchorsByVoice: Map<Int, String?>,
    onIndexChanged: (Int) -> Unit,
    onDismiss: () -> Unit,
    onSave: (TUOEditState) -> Unit
) {
    var currentIndex by remember(globalIndex) { mutableStateOf(globalIndex) }
    val notes = remember {
        mutableStateMapOf<Int, String>().apply {
            putAll(editState.notesByVoice)
        }
    }
    val isAndroid = remember { getPlatform().name.startsWith("Android") }
    val keyboardState = LocalSolfaKeyboardState.current
    val keyboardController = LocalSoftwareKeyboardController.current
    var selectedVoiceIndex by remember { mutableStateOf(0) }

    DisposableEffect(Unit) {
        keyboardState.isDialogActive = true
        onDispose {
            keyboardState.hide()
            keyboardState.isDialogActive = false
        }
    }
    val originalNotes = mutableStateMapOf<Int, String>().apply {
        putAll(editState.notesByVoice)
    }
    val originalLyricsByStz = mutableStateMapOf<Int, String>().apply {
        putAll(editState.lyricsByStanza)
    }

    var templateFragment by remember { mutableStateOf(editState.templateFragment) }
    var newSep by remember { mutableStateOf(editState.sep) }

    var marker by remember { mutableStateOf(editState.marker) }
    val initialSep = remember { editState.sep }
    val initialMarker = remember { editState.marker }

    LaunchedEffect(notes.toMap()) {
        val tempState = TUOEditState(
            tuoIndex = editState.tuoIndex,
            notesByVoice = notes.toMap(),
            originalNotes = editState.originalNotes,
            lyricsByStanza = editState.lyricsByStanza,
            originalLyricsByStanza = editState.originalLyricsByStanza,
            templateFragment = templateFragment,
            marker = editState.marker
        )

        // Màj auto template
        val newTemplate = getGlobalTemplate(tempState)
        if (newTemplate != templateFragment) {
            templateFragment = newTemplate
        }
    }

    val result = remember {
        mutableStateListOf<String>().apply {
            val existing = editState.lyricsByStanza[currentStanza] ?: ""
            if (existing.isEmpty() && canAdd) add("_") else add(existing)
        }
    }
    val lyricsLines = remember(editState.lyricsByStanza) {
        mutableStateListOf<String>().apply {
            addAll(editState.lyricsByStanza.values.toList())
        }
    }
    val editedLyricsMap = remember {
        mutableStateMapOf<Int, String>().apply {
            putAll(editState.lyricsByStanza)
        }
    }

    var showMarkerPopup by remember { mutableStateOf(false) }
    var markerButtonPos by remember {
        mutableStateOf(IntOffset.Zero)
    }
    LaunchedEffect(selectedVoiceIndex, notes[selectedVoiceIndex]) {
        if (keyboardState.isVisible) {
            val currentRawText = notes[selectedVoiceIndex] ?: ""
            keyboardState.currentText = transformMusicalInput(currentRawText)
        }
    }

    fun attachKeyboardToVoice(voiceIndex: Int) {
        selectedVoiceIndex = voiceIndex
        if(isAndroid) {
            keyboardController?.hide()

            val rawInitialText = notes[voiceIndex] ?: ""
            val formattedInitialText = transformMusicalInput(rawInitialText)
            keyboardState.currentText = formattedInitialText

            keyboardState.show(
                initialVoice = voiceIndex,
                initialValue = formattedInitialText,
                onNote = { noteToAdd ->
                    val currentText = notes[voiceIndex] ?: ""
                    val newText = currentText + noteToAdd
                    val formattedText = transformMusicalInput(newText)
                    notes[voiceIndex] = formattedText
                    keyboardState.currentText = formattedText
                },
                onDelete = {
                    val currentText = notes[voiceIndex] ?: ""
                    if (currentText.isNotEmpty()) {
                        val octaveRegex = Regex("['`,₁₂₃₄₅¹²³⁴⁵]+$")

                        val newText = if (octaveRegex.containsMatchIn(currentText)) {
                            currentText.replace(octaveRegex, "")
                        } else {
                            currentText.dropLast(1)
                        }

                        notes[voiceIndex] = transformMusicalInput(newText)
                        keyboardState.currentText = transformMusicalInput(newText)
                    }
                },
                onSymbol = { symbol ->
                    val currentText = notes[voiceIndex] ?: ""
                    val newText = currentText + symbol
                    notes[voiceIndex] = transformMusicalInput(newText)
                    keyboardState.currentText = transformMusicalInput(newText)
                },
                onClose = {
                    onDismiss()
                },
                onBuild = {
                    val finalLyricsMap = editState.lyricsByStanza.toMutableMap()
                    finalLyricsMap.putAll(editedLyricsMap)
                    if (!finalLyricsMap.containsKey(currentStanza)) {
                        finalLyricsMap[currentStanza] = lyricsLines.getOrNull(0)?.trim() ?: ""
                    }
                    val state = TUOEditState(
                        tuoIndex = globalIndex,
                        notesByVoice = notes.toMap(),
                        originalNotes = originalNotes.toMap(),
                        originalLyricsByStanza = originalLyricsByStz.toMutableMap(),
                        lyricsByStanza = finalLyricsMap,
                        templateFragment = templateFragment,
                        marker = if(marker.isEmpty()) "_" else marker,
                        originalSep = initialSep,
                        sep = newSep
                    )
                    onSave(state)
                },
                onTab = {
                    val nextVoice = (selectedVoiceIndex + 1) % 4
                    attachKeyboardToVoice(nextVoice)
                }
            )
        }
    }


    Popup(
        offset = menuPosition,
        onDismissRequest = {
            if(!isAndroid && !keyboardState.isVisible) {
                onDismiss()
            }
       },
        properties = PopupProperties(
            focusable = if(isAndroid) false else true,
            dismissOnBackPress = !isAndroid || !keyboardState.isVisible,
            dismissOnClickOutside = !isAndroid || !keyboardState.isVisible
        ),
    ) {
        Surface(
            modifier = Modifier
                .widthIn(max=125.dp)
                .heightIn(max = 400.dp)
                .imePadding()
                .navigationBarsPadding(),
            shape = MaterialTheme.shapes.small,
            color = MaterialTheme.colorScheme.onSecondaryContainer.copy(0.75f),
        ) {
            Column(modifier = Modifier.padding(horizontal = 10.dp, vertical = 5.dp).fillMaxWidth()) {
                Row (
                    modifier = Modifier.fillMaxWidth(),
                    horizontalArrangement = Arrangement.SpaceBetween,
                    verticalAlignment = Alignment.CenterVertically
                ) {
                    // Modif silence duration
                    if (currentIndex == 0) {
                        val silentDurationOrder = listOf(
                            "0", "4", "8", "A", "C", "E", "G", "K", "O", "S", "W"
                        )
                        Row(
                            modifier = Modifier.width(125.dp),
                            verticalAlignment = Alignment.CenterVertically,
                            horizontalArrangement = Arrangement.SpaceBetween
                        ) {
                            IconButton(
                                onClick = {
                                    val currentIdx = silentDurationOrder.indexOf(editState.silentDuration)
                                    val newIdx = if (currentIdx > 0) currentIdx - 1 else 0
                                    val newDuration = silentDurationOrder[newIdx]

                                    val state = TUOEditState(
                                        tuoIndex = globalIndex,
                                        notesByVoice = notes.toMap(),
                                        originalNotes = originalNotes.toMap(),
                                        originalLyricsByStanza = originalLyricsByStz.toMutableMap(),
                                        lyricsByStanza = mutableMapOf(currentStanza to lyricsLines.joinToString(" ")),
                                        templateFragment = templateFragment,
                                        marker = if(marker.isEmpty()) "_" else marker,
                                        silentDuration = newDuration
                                    )
                                    onSave(state)
                                },
                                enabled = silentDurationOrder.indexOf(editState.silentDuration) >= 0,
                                modifier = Modifier.size(20.dp)
                            ) {
                                Icon(
                                    imageVector = Icons.Default.KeyboardDoubleArrowLeft,
                                    contentDescription = "Diminuer",
                                    tint = if (silentDurationOrder.indexOf(editState.silentDuration) > 0) Color.LightGray else Color.DarkGray
                                )
                            }

                            Text(
                                text = editState.silentDuration,
                                color = Color.White,
                                style = MaterialTheme.typography.bodyLarge
                            )

                            IconButton(
                                onClick = {
                                    val currentIdx = silentDurationOrder.indexOf(editState.silentDuration)
                                    val newIdx = if (currentIdx != -1 && currentIdx < silentDurationOrder.lastIndex) currentIdx + 1 else currentIdx
                                    val newDuration = silentDurationOrder[newIdx]

                                    val state = TUOEditState(
                                        tuoIndex = globalIndex,
                                        notesByVoice = notes.toMap(),
                                        originalNotes = originalNotes.toMap(),
                                        originalLyricsByStanza = originalLyricsByStz.toMutableMap(),
                                        lyricsByStanza = mutableMapOf(currentStanza to lyricsLines.joinToString(" ")),
                                        templateFragment = templateFragment,
                                        marker = if(marker.isEmpty()) "_" else marker,
                                        silentDuration = newDuration
                                    )
                                    onSave(state)
                                },
                                enabled = silentDurationOrder.indexOf(editState.silentDuration) < silentDurationOrder.lastIndex,
                                modifier = Modifier.size(20.dp)
                            ) {
                                Icon(
                                    imageVector = Icons.Default.KeyboardDoubleArrowRight,
                                    contentDescription = "Augmenter",
                                    tint = if (silentDurationOrder.indexOf(editState.silentDuration) < silentDurationOrder.lastIndex) Color.LightGray else Color.DarkGray
                                )
                            }
                        }
                    }
                    if (currentIndex > 0) {
                        IconButton(
                            onClick = {
                                currentIndex--
                                onIndexChanged(currentIndex)
                            },
                            modifier = Modifier.size(32.dp)
                        ) {
                            Icon(
                                imageVector = Icons.AutoMirrored.Filled.ArrowBack,
                                contentDescription = "Précédent",
                                tint = Color.White
                            )
                        }

                        Text(
                            text = "N°$currentIndex",
                            fontSize = 15.sp,
                            fontWeight = FontWeight.Bold,
                            color = Color.White
                        )
                    }

                    IconButton(
                        onClick = {
                            currentIndex++
                            onIndexChanged(currentIndex)
                        },
                        modifier = Modifier.size(32.dp)
                    ) {
                        Icon(
                            imageVector = Icons.AutoMirrored.Filled.ArrowForward,
                            contentDescription = "Suivant",
                            tint = Color.White
                        )
                    }
                }

                Spacer(modifier = Modifier.height(2.dp))

                Column(
                    modifier = Modifier
                        .verticalScroll(rememberScrollState())
                ) {
                    // --- SECTION TEMPLATE ---
                    Row(horizontalArrangement = Arrangement.SpaceEvenly, verticalAlignment = Alignment.CenterVertically) {
                        if(globalIndex != 0 && templateFragment != "-") {
                            Column(
                                modifier = Modifier.width(20.dp)
                            ) {
                                val isSeparator = newSep == "/"
                                val tooltipText = if (isSeparator) {
                                    "Enlever la barre de mesure"
                                } else {
                                    "Ajouter une barre de mesure"
                                }

                                TooltipBox(
                                    positionProvider = TooltipDefaults.rememberPlainTooltipPositionProvider(),
                                    tooltip = {
                                        PlainTooltip(
                                            containerColor = Color.DarkGray,
                                            contentColor = Color.White
                                        ) {
                                            Text(text = tooltipText, fontSize = 12.sp)
                                        }
                                    },
                                    state = rememberTooltipState()
                                ) {
                                    if(isSeparator) {
                                        IconButton(
                                            modifier = Modifier.size(20.dp),
                                            onClick = {
                                                val state = TUOEditState(
                                                    tuoIndex = globalIndex,
                                                    notesByVoice = notes.toMap(),
                                                    originalNotes = originalNotes.toMap(),
                                                    originalLyricsByStanza = originalLyricsByStz.toMutableMap(),
                                                    lyricsByStanza = mutableMapOf(),
                                                    templateFragment = templateFragment,
                                                    marker = if(marker.isEmpty()) "_" else marker,
                                                    originalSep = initialSep,
                                                    sep = ""
                                                )
                                                onSave(state)
                                            }) {
                                            Text(
                                                text = "/",
                                                color = MaterialTheme.colorScheme.secondary.copy(alpha = 1.5f),
                                                fontSize = 18.sp,
                                                fontWeight = FontWeight.Bold,
                                                textAlign = TextAlign.Center
                                            )
                                        }
                                    } else {
                                        IconButton(
                                            modifier = Modifier.size(20.dp),
                                            onClick = {

                                                val state = TUOEditState(
                                                    tuoIndex = globalIndex,
                                                    notesByVoice = notes.toMap(),
                                                    originalNotes = originalNotes.toMap(),
                                                    originalLyricsByStanza = originalLyricsByStz.toMutableMap(),
                                                    lyricsByStanza = mutableMapOf(),
                                                    templateFragment = templateFragment,
                                                    marker = if(marker.isEmpty()) "_" else marker,
                                                    originalSep = initialSep,
                                                    sep = "/"
                                                )
                                                onSave(state)
                                            }) {
                                            Icon(
                                                imageVector = Icons.Default.Add,
                                                tint = MaterialTheme.colorScheme.secondary.copy(alpha = 1.5f),
                                                contentDescription = null
                                            )
                                        }
                                    }
                                }
                            }
                        }
                        Column(
                            modifier = Modifier.weight(1f)
                        ) {
                            MyTextEditField(
                                value = templateFragment,
                                customFontSize = 14.sp,
                                color = MaterialTheme.colorScheme.tertiary.copy(alpha = 1.5f),
                                customPadding = 8.dp,
                                customBrush = SolidColor(Color.White),
                                isEditable = false,
                                isAddable = false,
                                onValueChng = { templateFragment = it }
                            )

                        }

                        if (!templateFragment.isNullOrBlank() && templateFragment != "-") {
                            val hasMarker = marker.isNotEmpty()
                            val hairPinState by sharedScreenModel.isPendingHairPinOnEdit.collectAsState()

                            Row(verticalAlignment = Alignment.CenterVertically) {
                                if (hasMarker) {
                                    TooltipBox(
                                        positionProvider = TooltipDefaults.rememberPlainTooltipPositionProvider(),
                                        tooltip = {
                                            PlainTooltip(containerColor = Color.DarkGray, contentColor = Color.White) {
                                                Text(text = "Enlever le marqueur", fontSize = MaterialTheme.typography.titleSmall.fontSize)
                                            }
                                        },
                                        state = rememberTooltipState()
                                    ) {
                                        IconButton(
                                            modifier = Modifier.size(22.dp),
                                            onClick = {
                                                val state = TUOEditState(
                                                    tuoIndex = globalIndex,
                                                    notesByVoice = notes.toMap(),
                                                    originalNotes = originalNotes.toMap(),
                                                    originalLyricsByStanza = originalLyricsByStz.toMutableMap(),
                                                    lyricsByStanza = mutableMapOf(),
                                                    templateFragment = templateFragment,
                                                    marker = "_", // On remet le marqueur à vide
                                                    originalSep = initialSep,
                                                    sep = newSep
                                                )
                                                if(hairPinState.gridIndex == globalIndex) {
                                                    sharedScreenModel.setPendingHairPin(false)
                                                }
                                                onSave(state)
                                            }
                                        ) {
                                            Icon(
                                                imageVector = Icons.Sharp.Delete,
                                                tint = MaterialTheme.colorScheme.secondary.copy(alpha = 1.5f),
                                                contentDescription = "Enlever"
                                            )
                                        }
                                    }
                                }

                                if(hairPinState.isPending && hairPinState.gridIndex < globalIndex) {
                                    TooltipBox(
                                        positionProvider = TooltipDefaults.rememberPlainTooltipPositionProvider(),
                                        tooltip = {
                                            PlainTooltip(containerColor = Color.DarkGray, contentColor = Color.White) {
                                                Text(
                                                    text = "Complèter le marqueur",
                                                    fontSize = MaterialTheme.typography.titleSmall.fontSize
                                                )
                                            }
                                        },
                                        state = rememberTooltipState()
                                    ) {
                                        IconButton(
                                            modifier = Modifier.size(22.dp),
                                            onClick = {
                                                marker = "="
                                                val state = TUOEditState(
                                                    tuoIndex = globalIndex,
                                                    marker = marker
                                                )
                                                onSave(state)
                                            }
                                        ) {
                                            Icon(
                                                imageVector = Icons.Default.Check,
                                                tint = MaterialTheme.colorScheme.secondary.copy(alpha = 1.5f),
                                                contentDescription = null
                                            )
                                        }
                                    }
                                } else {
                                    TooltipBox(
                                        positionProvider = TooltipDefaults.rememberPlainTooltipPositionProvider(),
                                        tooltip = {
                                            PlainTooltip(containerColor = Color.DarkGray, contentColor = Color.White) {
                                                Text(
                                                    text = "Ajouter un marqueur",
                                                    fontSize = MaterialTheme.typography.titleSmall.fontSize
                                                )
                                            }
                                        },
                                        state = rememberTooltipState()
                                    ) {
                                        IconButton(
                                            modifier = Modifier.size(22.dp)
                                                .onGloballyPositioned { coordinates ->
                                                    markerButtonPos = coordinates.positionInParent().let {
                                                        IntOffset(it.x.toInt(), it.y.toInt())
                                                    }
                                                },
                                            onClick = { showMarkerPopup = true }
                                        ) {
                                            Icon(
                                                imageVector = Icons.Default.Edit,
                                                tint = MaterialTheme.colorScheme.secondary.copy(alpha = 1.5f),
                                                contentDescription = null
                                            )
                                        }
                                    }
                                }
                            }
                        }

                    }

                    Spacer(modifier = Modifier.height(8.dp))

                    val activeMessages = (0..3).mapNotNull { voice ->
                        val currentNote = notes[voice] ?: ""
                        val validation = validateMusicalInput(currentNote, templateFragment)
                        if (validation.message.isNotEmpty() && currentNote.isNotEmpty()) validation else null
                    }

                    if (activeMessages.isNotEmpty()) {
                        val firstValidation = activeMessages.first()

                        Surface(
                            modifier = Modifier
                                .fillMaxWidth()
                                .padding(bottom = 12.dp),
                            shape = RoundedCornerShape(8.dp),
                            color = if (firstValidation.isValid) MaterialTheme.colorScheme.primary else MaterialTheme.colorScheme.tertiary.copy(alpha = 1.5f),
                            shadowElevation = 2.dp
                        ) {
                            Row(
                                modifier = Modifier.padding(horizontal = 12.dp, vertical = 2.dp),
                                verticalAlignment = Alignment.CenterVertically
                            ) {
                                Text(
                                    text = firstValidation.message,
                                    color = if (firstValidation.isValid) Color.White else Color.Black,
                                    fontSize = 13.sp,
                                    fontWeight = FontWeight.Medium
                                )
                            }
                        }
                    }
                    // --- SECTION NOTES ---
                    Column(
                        modifier = Modifier.fillMaxWidth(),
                        verticalArrangement = Arrangement.spacedBy(5.dp)
                    ) {
                        (0..3).forEach { voice ->
                            val currentNote = notes[voice] ?: ""
                            val validation = validateMusicalInput(currentNote, templateFragment)
                            val voiceAnchor = anchorsByVoice[voice]?.replace("#","")
                            val hasAnchor = !voiceAnchor.isNullOrBlank()
                            val isSelected = selectedVoiceIndex == voice && keyboardState.isVisible

                            Box(modifier = Modifier
                                //.wrapContentSize()
                                .fillMaxWidth()
                            ) {
                                if(!isAndroid) {
                                    MyTextEditField(
                                        value = currentNote ?: "",
                                        customFontSize = 14.sp,
                                        color = Color.White,
                                        customPadding = 8.dp,
                                        customBrush = SolidColor(Color.White),
                                        isEditable = isEditable,
                                        isAddable = canAdd,
                                        isWarn = !validation.isValid,
                                        funTransform = ::transformMusicalInput,
                                        onValueChng = { newValue ->
                                            notes[voice] = newValue
                                        }
                                    )
                                    if (hasAnchor) {
                                        Spacer(modifier = Modifier.width(2.dp))

                                        TooltipBox(
                                            positionProvider = TooltipDefaults.rememberPlainTooltipPositionProvider(),
                                            tooltip = {
                                                PlainTooltip(containerColor = Color.DarkGray, contentColor = Color.White) {
                                                    Text("Ancrée sur ${transformMusicalInput(voiceAnchor)}", fontSize = 11.sp)
                                                }
                                            },
                                            state = rememberTooltipState()
                                        ) {
                                            Surface(
                                                shape = RoundedCornerShape(3.dp),
                                                color = MaterialTheme.colorScheme.tertiary.copy(alpha = 0.8f),
                                                modifier = Modifier.padding(start = 2.dp)
                                            ) {
                                                Text(
                                                    text = "⚓",
                                                    fontSize = 10.sp,
                                                    color = Color.Black,
                                                    modifier = Modifier.padding(horizontal = 2.dp, vertical = 1.dp)
                                                )
                                            }
                                        }
                                    }
                                } else {
                                    SolfaTextEditField(
                                        value = currentNote ?: "",
                                        customFontSize = 14.sp,
                                        color = if (isSelected) MaterialTheme.colorScheme.tertiary else Color.White,
                                        customPadding = 8.dp,
                                        customBrush = SolidColor(Color.White),
                                        isWarn = !validation.isValid,
                                        readOnly = isAndroid,
                                        funTransform = ::transformMusicalInput,
                                        onValueChng = { newValue ->
                                            notes[voice] = newValue
                                        }
                                    )
                                }
                                if(isAndroid) {
                                    Box(
                                        modifier = Modifier
                                            .matchParentSize()
                                            .clickable {
                                                attachKeyboardToVoice(voice)
                                            }
                                    )
                                }
                            }
                        }
                    }

                    Spacer(modifier = Modifier.height(8.dp))

                    if(!isAndroid) {
                        // --- SECTION LYRICS ---
                        lyricsLines.forEachIndexed { index, line ->
                            val displayedLine = line
                            LaunchedEffect(displayedLine) {
                                if (displayedLine != line) {
                                    lyricsLines[index] = displayedLine
                                    val updatedLyricsMap = editState.lyricsByStanza.toMutableMap()
                                    updatedLyricsMap[index + 1] = displayedLine
                                }
                            }
                            Row(
                                verticalAlignment = Alignment.CenterVertically,
                                modifier = Modifier.padding(vertical = 2.dp)
                            ) {
                                Column(
                                    modifier = Modifier.fillMaxWidth(0.8f)
                                ) {

                                    val isLyricsValid = validateLyricsInput(line, templateFragment)
                                    val tooltipState2 = rememberTooltipState(isPersistent = false)
                                    Row(
                                    ) {
                                        TooltipBox(
                                            positionProvider = TooltipDefaults.rememberPlainTooltipPositionProvider(),
                                            tooltip = {
                                                if (!isLyricsValid) {
                                                    PlainTooltip(
                                                        containerColor = Color(0XFF34EB71),
                                                        contentColor = Color.White
                                                    ) {
                                                        Text("Veuillez suivre ce format: $templateFragment")
                                                    }
                                                }
                                            },
                                            state = tooltipState2
                                        ) {
                                            MyTextEditField(
                                                value = displayedLine,
                                                customFontSize = 13.sp,
                                                color = Color.White,
                                                customPadding = 8.dp,
                                                customBrush = SolidColor(Color.White),
                                                isEditable = isEditable,
                                                isAddable = canAdd,
                                                isWarn = !isLyricsValid,
                                                funTransform = { input ->
                                                    transformLyricsInput(
                                                        input,
                                                        templateFragment
                                                    )
                                                },
                                                onValueChng = { newValue ->
                                                    val trimmedValue = newValue.trimStart()
                                                    val dataToSave =
                                                        if (trimmedValue.endsWith(" ")) trimmedValue else "$trimmedValue "
                                                    lyricsLines[index] = trimmedValue
                                                    val updatedLyricsMap = editState.lyricsByStanza.toMutableMap()
                                                    editedLyricsMap[index + 1] = dataToSave

                                                    val updatedState = editState.copy(lyricsByStanza = updatedLyricsMap)
                                                }
                                            )
                                        }
                                    }
                                }
                                if (isEditable || canAdd) {
                                    IconButton(
                                        onClick = {
                                            if (index >= 0) {
                                                if (index == 0) lyricsLines.add("_") else lyricsLines.removeAt(index)
                                            }
                                        }) {
                                        Icon(
                                            imageVector = if (index == 0) Icons.Default.Add else Icons.Default.Clear,
                                            tint = if (index == 0) MaterialTheme.colorScheme.secondary.copy(alpha = 1.5f) else MaterialTheme.colorScheme.tertiary.copy(
                                                alpha = 1.5f
                                            ),
                                            contentDescription = null
                                        )
                                    }
                                }
                            }
                        }
                        Spacer(modifier = Modifier.height(10.dp))
                    }
                }

                if(!isAndroid) {
                    Row(
                        modifier = Modifier.fillMaxWidth(),
                        horizontalArrangement = Arrangement.End
                    ) {
                        IconButton(onClick = onDismiss, modifier = Modifier.size(20.dp)) {
                            Icon(
                                Icons.Default.Clear,
                                contentDescription = null,
                                tint = Color.LightGray
                            )
                        }
                        if (isEditable || canAdd) {
                            IconButton(
                                onClick = {
                                    val finalLyricsMap = editState.lyricsByStanza.toMutableMap()
                                    finalLyricsMap.putAll(editedLyricsMap)
                                    if (!finalLyricsMap.containsKey(currentStanza)) {
                                        finalLyricsMap[currentStanza] = lyricsLines.getOrNull(0)?.trim() ?: ""
                                    }
                                    val state = TUOEditState(
                                        tuoIndex = globalIndex,
                                        notesByVoice = notes.toMap(),
                                        originalNotes = originalNotes.toMap(),
                                        originalLyricsByStanza = originalLyricsByStz.toMutableMap(),
                                        lyricsByStanza = finalLyricsMap,
                                        templateFragment = templateFragment,
                                        marker = if(marker.isEmpty()) "_" else marker,
                                        originalSep = initialSep,
                                        sep = newSep
                                    )
                                    onSave(state)
                                },
                                modifier = Modifier.size(22.dp)
                            ) {
                                Icon(
                                    Icons.Default.Build,
                                    contentDescription = null,
                                    tint = MaterialTheme.colorScheme.secondary.copy(alpha = 1.5f)
                                )
                            }
                        }
                    }
                }
            }
        }
    }
    if (showMarkerPopup) {
        MarkerPopup(
            menuPosition = IntOffset(
                x = markerButtonPos.x + 180,
                y = markerButtonPos.y + 100
            ),
            onDismiss = {
                showMarkerPopup = false
            },
            onMarkerSelected = { newMarker ->
                showMarkerPopup = false
                val cleanMarker = marker.trim().replace(Regex("""\s+"""), " ")
                val modulaRegex = Regex("""D(ô|o)?\s*dia\s*(C|Db|D|Eb|E|F|Gb|G|Ab|A|Bb|B)""", RegexOption.IGNORE_CASE)
                val formattedExisting = modulaRegex.replace(cleanMarker) { match ->
                    "c:${match.groupValues[2]}"
                }
                val formattedMod = modulaRegex.replace(newMarker) { match -> "c:${match.groupValues[2]}"}

                val markerToSave = if (TimeUnitObject._hasMarker) {
                    "${formattedExisting.trim()} ${formattedMod.trim()} "
                } else {
                    "${formattedMod.trim()} "
                }

                val state = TUOEditState(
                    tuoIndex = globalIndex,
                    notesByVoice = notes.toMap(),
                    originalNotes = originalNotes.toMap(),
                    originalLyricsByStanza = originalLyricsByStz.toMutableMap(),
                    lyricsByStanza =  mutableMapOf(),
                    templateFragment = templateFragment,
                    marker = markerToSave,
                    originalSep = initialSep,
                    sep = newSep
                )
                onSave(state)
            }
        )
    }
}

private fun unpackLyrics(lyrics: String): String {
    val comments = Solfa.REGEX_COMMENT.findAll(lyrics)
    val commentsIterator = comments.iterator()
    val loadedLyrics = lyrics
        .replace(Solfa.REGEX_LYRICS_REPETITION) { matchResult ->
            val repeating = matchResult.destructured.match.groupValues[1]
            "_".repeat(repeating.toString().toInt())
        }
        .replace(Regex("(?<![\\?:,\\.; ])_"), "-_")
        .replace(Regex("_-(?=_)"), "_")
        .replace(" -_", "_")
        .replace("--_", "-_")
        .replace(Regex("_$"), "")

    val lyricsFinal = Solfa.REGEX_COMMENT.replace(loadedLyrics) { matchResult ->
        commentsIterator.next().value
    }
    return lyricsFinal
}
private fun smartYLyrics(lyrics: String): String {
    val comments = Solfa.REGEX_COMMENT.findAll(lyrics)
    val commentsIterator = comments.iterator()
    val loadedLyrics = lyrics
        .replace(Solfa.REGEX_VOWELS_STAGE1, "$0_")
        .replace(Solfa.REGEX_VOWELS_STAGE2, "$1_")
        .replace(Solfa.REGEX_VOWELS_STAGE3, "$1_")
        .replace(" ", " _")
        .replace("_\\ _", " ")
        .replace("_\\", "")
        .replace("_0", "")
        .replace(Solfa.REGEX_MALAGASY_MN, "$1$2_$3")
        .replace(Solfa.REGEX_MALAGASY_MN_STAGE2, "$1-_")
        .replace("_n'", "n'_")
    val lyricsFinal = Solfa.REGEX_COMMENT.replace(loadedLyrics) { matchResult ->
        commentsIterator.next().value
    }
    return unpackLyrics(lyricsFinal)
}
public fun transformLyricsInput(input: String, template: String): String {
    val templateCount = template.count { it.isLetter() && it.lowercaseChar() != 'z' }

    val processed = smartYLyrics(input)
    val currentSyllables = processed.split("_").filter { it.isNotEmpty() }
    val currentCount = currentSyllables.size

//    println("\n\n\tDEBUG [Start] Input: '$input' | TemplateCount: $templateCount | Found: $currentCount ${currentSyllables.joinToString("|")}")
//    println("DEBUG [Segments]: $currentSyllables")

    val rawResult = if (currentCount <= templateCount) {
//        println("DEBUG [Status]: Pas de fusion nécessaire.")
        input
    } else {
        val parts = currentSyllables.toMutableList()
        val excess = currentCount - templateCount
//        println("DEBUG [Fusion]: Besoin de fusionner $excess fois.")

        for (i in 0 until excess) {
            val idx = parts.size - 2/* - i*/
            if (idx >= 0) {
//                println("DEBUG [Loop $i]: Fusion de l'index $idx avec ${idx + 1}")
//                println("DEBUG [Avant]: '${parts[idx]}' et '${parts[idx + 1]}'")
                val part1 = parts[idx].trimEnd()
                val part2 = parts[idx + 1].trimStart()
                val cleanPart1 = part1.replace("-", "")
                val lastChar = if (cleanPart1.isNotEmpty()) cleanPart1.last() else ' '

                val endsWithVowel = "aeiouyòàéìỳAEIOUY".contains(lastChar)
                val isVowelConsonantPair = endsWithVowel && part2.length == 1 && !"aeiouyòàéìỳAEIOUY".contains(part2.first())

                if (part2.isNotEmpty()) {
                    if (isVowelConsonantPair) {
                        parts[idx] = part1 + part2
                    } else {
                        parts[idx] = part1 + "\\ " + part2
                    }
                } else {
                    parts[idx] = part1 + "\\"
                }
                parts.removeAt(idx + 1)
            }
//            println("DEBUG [Après]: Résultat index $idx -> '${parts}'")
        }

        val result = parts.joinToString("")
//        println("DEBUG [Final]: '$result'")
        result
    }
    val REGEX_MALAGASY_MN_OUTPUT = Regex("-([mn])")
    val correctedResult = rawResult.replace(REGEX_MALAGASY_MN_OUTPUT, "$1-")

    if (correctedResult != rawResult) {
//        println("DEBUG [Correction MN]: '$rawResult' -> '$correctedResult'")
    }
    return correctedResult
}
private fun transformMusicalInput(input: String): String {
    return input.lowercase()
        .replace(";", "• ,")
        .replace(".", "•")
        .replace("-", "―")
        .replace("(?<=[a-z])[']".toRegex(), "¹")
        .replace("(?<=[a-z])[,]".toRegex(), "₁")
        .replace("¹¹", "²")
        .replace("¹'", "²")
        .replace("²¹", "³")
        .replace("²'", "³")
        .replace("³'", "⁴")
        .replace("³¹", "⁴")
        .replace("₁,", "₂")
        .replace("₁₁", "₂")
        .replace("₂,", "₃")
        .replace("₂₁", "₃")
        .replace("₃,", "₄")
        .replace("₃₁", "₄")
        .replace("'", "¹")
}
private fun transformMarkerInput(input: String): String {
    return input
        .replace("dc", "DC")
        .replace("ds", "DS")
        .replace(".)", "\uD834\uDD10")
}

@Composable
fun MyTextEditField(
    value: String,
    customFontSize: TextUnit,
    font: FontFamily? = FontFamily.SansSerif,
    color: Color,
    customPadding: Dp,
    customBrush: Brush,
    isEditable: Boolean,
    isAddable: Boolean,
    isWarn: Boolean? = false,
    funTransform: ((String) -> String)? = null,
    onValueChng: (String) -> Unit
) {
    var textFieldValueState by remember {
        mutableStateOf(TextFieldValue(text = value, selection = TextRange(value.length)))
    }

    LaunchedEffect(value) {
        if (textFieldValueState.text != value) {
            val newSelection = if (textFieldValueState.selection.start <= value.length) {
                textFieldValueState.selection
            } else {
                TextRange(value.length)
            }
            textFieldValueState = TextFieldValue(text = value, selection = newSelection)
        }
    }
    val textToShow = if (isAddable && value == "_") "" else textFieldValueState.text

    BasicTextField(
        value = textFieldValueState,
        onValueChange = { newValue ->
            if (isEditable || isAddable) {
                val transformedText = funTransform?.invoke(newValue.text) ?: newValue.text
                val finalSelection = if (transformedText.length != newValue.text.length) {
                    if (newValue.selection.start <= transformedText.length) newValue.selection else TextRange(transformedText.length)
                } else {
                    newValue.selection
                }

                textFieldValueState = TextFieldValue(
                    text = transformedText,
                    selection = finalSelection
                )
                onValueChng(transformedText)
            }
        },
        keyboardOptions = KeyboardOptions(
            autoCorrectEnabled = false,
            keyboardType = KeyboardType.Ascii
        ),
        textStyle = TextStyle(
            color = color,
            fontSize = customFontSize,
            fontFamily = font
        ),
        readOnly = !(isEditable || isAddable),
        modifier = Modifier
            .fillMaxWidth()
            .background(Color.Black.copy(alpha = 0.3f), RoundedCornerShape(4.dp))
            .border(
                if (isWarn!!) 1.dp else 0.dp,
                if (isWarn!!) MaterialTheme.colorScheme.tertiary.copy(alpha = 1.5f) else Color.Transparent,
                shape = RoundedCornerShape(4.dp)
            )
            .padding(customPadding),
        cursorBrush = customBrush
    )
}

@Composable
fun SolfaTextEditField(
    value: String,
    customFontSize: TextUnit,
    font: FontFamily? = FontFamily.SansSerif,
    color: Color,
    customPadding: Dp,
    customBrush: Brush,
    isWarn: Boolean? = false,
    readOnly: Boolean,
    funTransform: ((String) -> String)? = null,
    onValueChng: (String) -> Unit
) {
    var textFieldValueState by remember {
        mutableStateOf(TextFieldValue(text = value, selection = TextRange(value.length)))
    }

    LaunchedEffect(value) {
        if (textFieldValueState.text != value) {
            val newSelection = if (textFieldValueState.selection.start <= value.length) {
                textFieldValueState.selection
            } else {
                TextRange(value.length)
            }
            textFieldValueState = TextFieldValue(text = value, selection = newSelection)
        }
    }

    BasicTextField(
        value = textFieldValueState,
        onValueChange = { newValue ->
            println("ça change $newValue => ${textFieldValueState.text}")
            val transformedText = funTransform?.invoke(newValue.text) ?: newValue.text
            val finalSelection = if (transformedText.length != newValue.text.length) {
                if (newValue.selection.start <= transformedText.length) newValue.selection else TextRange(transformedText.length)
            } else {
                newValue.selection
            }

            textFieldValueState = TextFieldValue(
                text = transformedText,
                selection = finalSelection
            )
            println("et ça trnasforme en = $transformedText")
            onValueChng(transformedText)
        },
        keyboardOptions = KeyboardOptions(
            autoCorrectEnabled = false,
            keyboardType = KeyboardType.Ascii
        ),
        textStyle = TextStyle(
            color = color,
            fontSize = customFontSize,
            fontFamily = font
        ),
        readOnly = readOnly,
        modifier = Modifier
            .fillMaxWidth()
            .background(Color.Black.copy(alpha = 0.3f), RoundedCornerShape(4.dp))
            .border(
                if (isWarn!!) 1.dp else 0.dp,
                if (isWarn!!) MaterialTheme.colorScheme.tertiary.copy(alpha = 1.5f) else Color.Transparent,
                shape = RoundedCornerShape(4.dp)
            )
            .padding(customPadding),
        cursorBrush = customBrush
    )
}

data class ValidNoteResult(
    val isValid: Boolean,
    val message: String
)

private fun validateMusicalInput(input: String, template: String): ValidNoteResult {
    if (template.isEmpty()) return ValidNoteResult(false, "")

    /* Ajout > */
    val matchAddNote = Solfa.REGEX_NOTE_TOADD.find(input)
    if (matchAddNote != null) {
        val addedNote = matchAddNote.value.replace(">", "")
        val inserted = matchAddNote.groupValues[1] + matchAddNote.groupValues[2]
        val shifted = matchAddNote.groupValues[3] + matchAddNote.groupValues[4]

        return ValidNoteResult(
            isValid = true,
            message = "+ $inserted ↠ $shifted"
        )
    }

    /* Suppress < */
    if (input.contains("<")) {
        val matchDropNote = Solfa.REGEX_NOTE_TODROP.find(input)
        val isValidDrop = matchDropNote != null/* && input.endsWith("<")*/

        if (isValidDrop) {
            val noteBase: String = matchDropNote.groupValues[1]
            val octave: String = matchDropNote.groupValues[2]
            val droppedNote = noteBase + octave
            return ValidNoteResult(
                isValid = true,
                message = "$droppedNote ⌫ ?"
            )
        } else {
            return ValidNoteResult(
                isValid = false,
                message = "< incorrect"
            )
        }
    }
    val cleanInput = input
        .replace("(", "")
        .replace(")", "")
        .replace(" ", "")
        .replace(Solfa.REGEX_NOTE_TOADD, "$3$4")
        .replace(Solfa.REGEX_NOTE_TODROP, "$1$2")
    val cleanTemplate = template.replace("(", "").replace(")", "")

    val regexPattern = buildString {
        cleanTemplate.forEachIndexed { index, char ->
            when (char) {
                in 'A'..'Y', in 'a'..'y' -> {
                    append("(?:―|di|ri|fi|si|ta|[drmfsltz])[₄₃₂₁¹²³⁴]*")
                }
                'z' -> {
                    append(" ?")
                }

                '.' -> append("•")
                ',' -> append(",")
                '-' -> {
                    val prev = if (index > 0) cleanTemplate[index - 1] else null
                    val next = if (index < cleanTemplate.lastIndex) cleanTemplate[index + 1] else null

                    if (prev == '.' && next == ',') {
                        append("?[\\s]*")
                    } else {
                        append("―")
                    }
                }
                else -> append(Regex.escape(char.toString()))
            }
        }
    }

    val regex = Regex("^$regexPattern$")
    val isMatched = regex.matches(cleanInput)

    /*println("""
        ┌──────────────────────────────────────────────────────────
        │  DÉBOGAGE VALIDATION
        ├──────────────────────────────────────────────────────────
        │  Template Origine : $template
        │ ️ Regex Générée   : ^$regexPattern$
        │  Input Reçu      : "$input"
        │ Résultat        : ${if (isMatched) "VALIDE (OUI)" else "INVALIDE (NON)"}
        └──────────────────────────────────────────────────────────
    """.trimIndent())*/

    return if (isMatched) {
        ValidNoteResult(isValid = true, message = "")
    } else {
        ValidNoteResult(isValid = false, message = "Erreur")
    }
}

private fun validateLyricsInput(cleanInput: String, template: String): Boolean {
    val vowels = "aeiouyòàéìỳAEIOUY"

    val expectedSyllableCount = template.count { it.lowercaseChar() != 'z' && it.isLetter() }

    val syllableRegex = Regex("[^aeiouyòàéìỳAEIOUY]*[aeiouyòàéìỳAEIOUY]+[^aeiouyòàéìỳAEIOUY]*", RegexOption.IGNORE_CASE)

    val foundSyllables = syllableRegex.findAll(cleanInput).toList()
    val rawSyllableCount = foundSyllables.size
    val backslashCount = cleanInput.count { it == '\\' }

    val actualSyllableCount = if (backslashCount > 0) {
        (rawSyllableCount - backslashCount).coerceAtLeast(1)
    } else {
        rawSyllableCount
    }
    /*println("""
        ┌──────────────────────────────────────────────────────────
        │  VALIDATION LYRICS
        ├──────────────────────────────────────────────────────────
        │  Template    : "$template"
        │  Input       : "$cleanInput"
        │  Attendu     : $expectedSyllableCount syllabes
        │  Trouvé      : $actualSyllableCount syllabes
        └──────────────────────────────────────────────────────────
    """.trimIndent())*/

    return actualSyllableCount == expectedSyllableCount
}

public fun getGlobalTemplate(editState: TUOEditState): String {
//    println("\n--- DÉBOGAGE getGlobalTemplate ---")

    val voiceTemplates = (0..3).map { voiceIdx ->
        val notes = editState.notesByVoice[voiceIdx] ?: ""
        val filteredNotes = notes
            .replace(Solfa.REGEX_NOTE_TOADD, "$3$4")
            .replace("<", "")
        val tpl = notesToTemplate(filteredNotes).replace(Regex("[()]"), "")
//        println("Voix $voiceIdx | Notes: '$filteredNotes' -> Template: '$tpl'")
        tpl
    }

    val rythmicTemplates = voiceTemplates
    val maxLen = rythmicTemplates.maxOfOrNull { it.length } ?: 1
//     println("Longueur rythmique max détectée: $maxLen")

    val result = StringBuilder()

    for (i in 0 until maxLen) {
        val chars = rythmicTemplates.mapNotNull { it.getOrNull(i) }.toSet()
        val previousChars = if(i>0) rythmicTemplates.mapNotNull { it.getOrNull(i-1) }.toSet() else "".toSet()
        val activeChars = rythmicTemplates.mapNotNull { it.getOrNull(i) }
        val isAllHyphen = activeChars.isNotEmpty() && activeChars.all { it == '-' }

        val combinedChar = when {
            chars.contains('D') -> 'D'
            isAllHyphen         -> '-'
            chars.contains('.') -> '.'
            chars.contains(',') -> ','
            previousChars.contains('.') && chars.contains(' ') -> 'z'
            else                -> ' '
        }
        if (combinedChar == ',' && result.isNotEmpty() && result.last() == ' ') {
            result.deleteCharAt(result.length - 1)
        }
//        println("Pour $i = ${chars.toString()} on a > ${combinedChar.toString()}")

        val lastChar = if (result.isNotEmpty()) result.last() else null
        if (!((combinedChar == '.' && lastChar == '.') || (combinedChar == ',' && lastChar == ','))) {
            result.append(combinedChar)
        }
//        println("all = ${result.toString()}")
    }

//    println("Template Global Final: '${result.toString()}'")
//    println("----------------------------------\n")
    return result.toString()
}

private fun notesToTemplate(notes: String): String {
    if (notes.isEmpty()) return "z"

    val cleaned = notes
        .replace("―", "-")
        .replace("•", ".")
        .replace(Regex("[³₃²₂¹₁]"), "")
        .replace("di", "D")
        .replace("ri", "R")
        .replace("fi", "F")
        .replace("si", "S")
        .replace("ta", "T")

    val noteRegex = Regex("""([drmfsltDRFSTz][ia]?|[.,()\s-])""")
    val template = StringBuilder()
    val matches = noteRegex.findAll(cleaned)

    for (match in matches) {
        val value = match.value
        when {
            value.matches(Regex("[.,-]")) -> template.append(value)
            value.trim().isEmpty() -> template.append(" ")
            value.matches(Regex("[()]")) -> template.append("")
            else -> template.append("D")
        }
    }

    return template.toString()
}