package main

import androidx.compose.foundation.border
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.material.*
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ArrowBack
import androidx.compose.material.icons.filled.Check
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.focus.FocusRequester
import androidx.compose.ui.focus.focusRequester
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.input.key.*
import androidx.compose.ui.unit.dp
import kotlinx.serialization.encodeToString
import kotlinx.serialization.json.Json
import main.component.buttonComponent
import java.io.File
import java.io.IOException


var appState = AppState
@OptIn(ExperimentalMaterialApi::class, ExperimentalComposeUiApi::class)
@Composable
fun formPage(glossary: Glossary, onCancelClick: () -> Unit) {
    // State to track whether to show the snackbar
    AppState
    val requiredFieldsSnackbarVisibleState = remember { mutableStateOf(false) }
    val alreadyExistSnackbarVisibleState = remember { mutableStateOf(false) }

    val name = remember { mutableStateOf("") }
    val description = remember { mutableStateOf("") }
    val mainContext = remember { mutableStateOf("") }
    val secondaryContext = remember { mutableStateOf("") }
    val relatedTo = remember { mutableStateOf("") }
    val synonymous = remember { mutableStateOf("") }
    val antonym = remember { mutableStateOf("") }

    val openDialog = remember { mutableStateOf(false) }
    if (openDialog.value) {
        AlertDialog(
            onDismissRequest = {
                openDialog.value = false
            },
            title = {
                Text(text = "Confirmation d'ajout de mot")
            },
            text = {
                Text("Le mot '${name.value}' a bien été ajouté au glossaire.")
            },
            confirmButton = {
                buttonComponent(
                    onClick = {
                        openDialog.value = false
                        resetFields(name, description, mainContext, secondaryContext, relatedTo, synonymous, antonym)
                    },
                    width = 100,
                    text = "Fermer"
                )
            }
        )
    }
    MaterialTheme {
        val focusRequesters = List(7) { FocusRequester() }
        Column(
            modifier = Modifier.padding(16.dp),
            verticalArrangement = Arrangement.spacedBy(8.dp),
            horizontalAlignment = Alignment.CenterHorizontally
        ) {
            Text(text = "Nouveau mot", style = MaterialTheme.typography.h5)

            TextField(
                value = name.value,
                onValueChange = { name.value = it },
                label = { Text("Mot *") },
                singleLine = true,
                colors = TextFieldDefaults.textFieldColors(
                    focusedIndicatorColor = customRedColor,
                    unfocusedIndicatorColor = Color.Gray,
                    focusedLabelColor = customRedColor
                ),
                modifier = Modifier
                    .focusRequester(focusRequesters[0])
                    .onKeyEvent { event ->
                        if (event.type == KeyEventType.KeyDown && event.key == Key.Tab) {
                            focusRequesters[1].requestFocus()
                            true
                        } else {
                            false
                        }
                    }
            )

            TextField(
                value = description.value,
                onValueChange = { description.value = it },
                label = { Text("Description") },
                singleLine = true,
                colors = TextFieldDefaults.textFieldColors(
                    focusedIndicatorColor = customRedColor,
                    unfocusedIndicatorColor = Color.Gray,
                    focusedLabelColor = customRedColor
                ),
                modifier = Modifier
                    .focusRequester(focusRequesters[1])
                    .onKeyEvent { event ->
                        if (event.type == KeyEventType.KeyDown && event.key == Key.Tab && !event.isShiftPressed) {
                            focusRequesters[2].requestFocus()
                            true
                        } else if (event.type == KeyEventType.KeyDown && event.key == Key.Tab && event.isShiftPressed) {
                            focusRequesters[0].requestFocus()
                            true
                        } else {
                            false
                        }
                    }
            )


            var expanded by remember { mutableStateOf(false) }

            val glossaryWords = loadDatasFromFile(glossary.jsonFilePath)
            var contextList: List<String> = emptyList()
            glossaryWords.forEach { word: Word ->
                contextList = contextList + word.mainContext
            }
            contextList = contextList.distinct()

            var listToShow by remember(mainContext.value) {
                mutableStateOf(contextList.filter { it.startsWith(mainContext.value, ignoreCase = true) })
            }


            TextField(
                value = mainContext.value,
                onValueChange = {
                    mainContext.value = it
                    expanded = true
                    listToShow = contextList.filter { word -> word.startsWith(mainContext.value, ignoreCase = true) }

                },
                singleLine = true,
                label = { Text("Contexte principal *") },
                colors = TextFieldDefaults.textFieldColors(
                    focusedIndicatorColor = customRedColor,
                    unfocusedIndicatorColor = Color.Gray,
                    focusedLabelColor = customRedColor
                ),
                modifier = Modifier
                    .focusRequester(focusRequesters[2])
                    .onKeyEvent { event ->
                        if (event.type == KeyEventType.KeyDown && event.key == Key.Tab && !event.isShiftPressed) {
                            focusRequesters[3].requestFocus()
                            true
                        } else if (event.type == KeyEventType.KeyDown && event.key == Key.Tab && event.isShiftPressed) {
                            focusRequesters[1].requestFocus()
                            true
                        } else {
                            false
                        }
                    }

            )
            var dropHeight = (listToShow.count() * 60 + 30)

            if (dropHeight > 300){
                dropHeight = 300
            }

            if (expanded && mainContext.value.isNotBlank() && listToShow.isNotEmpty()) {
                Box(
                    modifier = Modifier
                        .height(dropHeight.dp)
                    .padding(10.dp)
                    .border(1.dp, Color.Black)
                ) {
                    val scrollState = rememberLazyListState()
                    LazyColumn(
                        state = scrollState,
                        modifier = Modifier.padding(10.dp),
                        verticalArrangement = Arrangement.spacedBy(10.dp)
                    ) {

                        listToShow.forEach { word ->
 
                            item {
                                Box(
                                    modifier = Modifier

                                        .width(300.dp)
                                        .clickable {
                                            mainContext.value = word
                                            expanded = false
                                        }
                                        .border(1.dp, Color.Black)
                                        .height(50.dp)
                                        .padding(10.dp)
                                        .clip(MaterialTheme.shapes.medium)


                                ) {
                                    Text(text = word)
                                }
                            }
                        }
                    }
                }
            }



            TextField(
                value = secondaryContext.value,
                onValueChange = { secondaryContext.value = it },
                label = { Text("Contexte secondaire") },
                singleLine = true,
                colors = TextFieldDefaults.textFieldColors(
                    focusedIndicatorColor = customRedColor,
                    unfocusedIndicatorColor = Color.Gray,
                    focusedLabelColor = customRedColor
                ),
                modifier = Modifier
                    .focusRequester(focusRequesters[3])
                    .onKeyEvent { event ->
                        if (event.type == KeyEventType.KeyDown && event.key == Key.Tab && !event.isShiftPressed) {
                            focusRequesters[4].requestFocus()
                            true
                        } else if (event.type == KeyEventType.KeyDown && event.key == Key.Tab && event.isShiftPressed) {
                            focusRequesters[2].requestFocus()
                            true
                        } else {
                            false
                        }
                    }
            )

            TextField(
                value = relatedTo.value,
                onValueChange = { relatedTo.value = it },
                label = { Text("Lié à") },
                singleLine = true,
                colors = TextFieldDefaults.textFieldColors(
                    focusedIndicatorColor = customRedColor,
                    unfocusedIndicatorColor = Color.Gray,
                    focusedLabelColor = customRedColor
                ),
                modifier = Modifier
                    .focusRequester(focusRequesters[4])
                    .onKeyEvent { event ->
                        if (event.type == KeyEventType.KeyDown && event.key == Key.Tab && !event.isShiftPressed) {
                            focusRequesters[5].requestFocus()
                            true
                        } else if (event.type == KeyEventType.KeyDown && event.key == Key.Tab && event.isShiftPressed) {
                            focusRequesters[3].requestFocus()
                            true
                        } else {
                            false
                        }
                    }
            )

            TextField(
                value = synonymous.value,
                onValueChange = { synonymous.value = it },
                label = { Text("Synonyme") },
                singleLine = true,
                colors = TextFieldDefaults.textFieldColors(
                    focusedIndicatorColor = customRedColor,
                    unfocusedIndicatorColor = Color.Gray,
                    focusedLabelColor = customRedColor
                ),
                modifier = Modifier
                    .focusRequester(focusRequesters[5])
                    .onKeyEvent { event ->
                        if (event.type == KeyEventType.KeyDown && event.key == Key.Tab && !event.isShiftPressed) {
                            focusRequesters[6].requestFocus()
                            true
                        } else if (event.type == KeyEventType.KeyDown && event.key == Key.Tab && event.isShiftPressed) {
                            focusRequesters[4].requestFocus()
                            true
                        } else {
                            false
                        }
                    }
            )

            TextField(
                value = antonym.value,
                onValueChange = { antonym.value = it },
                label = { Text("Antonyme") },
                singleLine = true,
                colors = TextFieldDefaults.textFieldColors(
                    focusedIndicatorColor = customRedColor,
                    unfocusedIndicatorColor = Color.Gray,
                    focusedLabelColor = customRedColor
                ),
                modifier = Modifier
                    .focusRequester(focusRequesters[6])
                    .onKeyEvent { event ->
                        if (event.type == KeyEventType.KeyDown && event.key == Key.Tab && !event.isShiftPressed) {
                            true
                        } else if (event.type == KeyEventType.KeyDown && event.key == Key.Tab && event.isShiftPressed) {
                            focusRequesters[5].requestFocus()
                            true
                        } else {
                            false
                        }
                    }
            )

            Row(
                modifier = Modifier.fillMaxWidth(),
                horizontalArrangement = Arrangement.SpaceEvenly
            ) {
                buttonComponent(onClick = onCancelClick, width = 150, text = "Retour", icon = Icons.Default.ArrowBack)
                buttonComponent(
                    onClick = {
                        // Validate the fields
                        if (name.value.isBlank() || mainContext.value.isBlank()) {
                            // Show the snackbar when validation fails
                            requiredFieldsSnackbarVisibleState.value = true
                            return@buttonComponent
                        }

                        val wordsList = loadDatasFromFile(glossary.jsonFilePath).toMutableList()

                        // Transform name to lowercase to avoid duplicates
                        name.value = name.value.lowercase()

                        // Verify if the word already exists in the glossary
                        if (wordsList.any { it.name.equals(name.value, ignoreCase = true) }) {
                            println("Le mot '${name.value}' existe déjà dans le glossaire. Ajout annulé.")
                            alreadyExistSnackbarVisibleState.value = true
                            return@buttonComponent
                        }

                        val newWord = Word(
                            name = name.value,
                            description = description.value,
                            mainContext = mainContext.value,
                            secondaryContext = secondaryContext.value,
                            relatedTo = relatedTo.value,
                            synonymous = synonymous.value,
                            antonym = antonym.value
                        )

                        addWordToGlossary(glossary.jsonFilePath, newWord)
                        openDialog.value = true

                    },
                    width = 150,
                    text = "Valider",
                    icon = Icons.Default.Check
                )
            }

            // Show the snackbar when the state is true
            if (requiredFieldsSnackbarVisibleState.value) {
                Snackbar(
                    modifier = Modifier.padding(16.dp),
                    action = {
                        buttonComponent(
                            onClick = { requiredFieldsSnackbarVisibleState.value = false },
                            width = 100,
                            text = "OK")
                    }
                ) {
                    Text("Les champs 'Mot' et 'Contexte principal' sont obligatoires.")
                }
            }
            if (alreadyExistSnackbarVisibleState.value) {
                Snackbar(
                    modifier = Modifier.padding(16.dp),
                    action = {
                        buttonComponent(
                            onClick = { alreadyExistSnackbarVisibleState.value = false },
                            width = 100,
                            text = "OK")
                    }
                ) {
                    Text("Le mot '${name.value}' existe déjà dans le glossaire. Ajout annulé.")
                }
            }
        }
    }
}


fun resetFields(
    name: MutableState<String>,
    description: MutableState<String>,
    mainContext: MutableState<String>,
    secondaryContext: MutableState<String>,
    relatedTo: MutableState<String>,
    synonymous: MutableState<String>,
    antonym: MutableState<String>
) {
    name.value = ""
    description.value = ""
    mainContext.value = ""
    secondaryContext.value = ""
    relatedTo.value = ""
    synonymous.value = ""
    antonym.value = ""
}

fun addWordToGlossary(filePath: String, newWord: Word) {
    val wordsList = loadDatasFromFile(filePath).toMutableList()

    // Verify if the word already exists in the glossary
    if (wordsList.any { it.name.equals(newWord.name, ignoreCase = true) }) {
        println("Le mot '${newWord.name}' existe déjà dans le glossaire. Ajout annulé.")
        return
    }

    // Add the new word to the glossary
    wordsList.add(newWord)
    saveDatasInFile(filePath, wordsList)

    println("Mot ajouté avec succès : ${newWord.name}")
}

fun saveDatasInFile(filePath: String, listeWords: List<Word>) {
    val json = Json { prettyPrint = true }
    try {
        val content = json.encodeToString(listeWords)
        File(glossaryPath + (appState.selectedProject?.name ) + "/" + filePath).writeText(content)
    } catch (e: IOException) {
        e.printStackTrace()
    }
}

fun loadDatasFromFile(filePath: String): List<Word> {
    // If file is empty, return empty list

    if (!File(glossaryPath + (appState.selectedProject?.name ) + "/" + filePath).exists() || File(glossaryPath + (appState.selectedProject?.name ) + "/" + filePath).length() == 0L) {
        return emptyList()
    }
    return try {
        val content = File(glossaryPath + (appState.selectedProject?.name ) + "/" + filePath).readText()
        Json.decodeFromString<List<Word>>(content)
    } catch (e: IOException) {
        e.printStackTrace()
        emptyList() // Handle the exception as needed
    }
}