package main

import androidx.compose.foundation.VerticalScrollbar
import androidx.compose.foundation.layout.*
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.rememberScrollbarAdapter
import androidx.compose.material.*
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Delete
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.ExperimentalComposeUiApi
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.input.key.*
import androidx.compose.ui.unit.dp
import main.component.dropdownButtonComponent
import org.apache.poi.ss.usermodel.CellType
import org.apache.poi.ss.usermodel.Workbook
import org.apache.poi.xssf.usermodel.XSSFWorkbook
import java.awt.FileDialog
import java.awt.Frame
import java.io.File
import java.io.FileInputStream
import java.io.FileWriter
import java.io.IOException
import javax.swing.JFileChooser
import javax.swing.filechooser.FileSystemView


data class Glossary(val name: String, val jsonFilePath: String)

val frame = Frame()

@Composable
fun glossaryItem(
    glossary: Glossary,
    onGlossarySelected: (Glossary) -> Unit,
    onGlossaryDelete: (Glossary) -> Unit
) {
    Row(
        modifier = Modifier.width(200.dp).fillMaxWidth(),
        horizontalArrangement = Arrangement.SpaceBetween
    ) {
        Button(
            onClick = {
                onGlossarySelected(glossary)
            },
            modifier = Modifier.width(150.dp),
            colors = ButtonDefaults.buttonColors(
                backgroundColor = customRedColor,
                contentColor = Color.White
            )
        ) {
            Text(glossary.name)
        }

        IconButton(
            onClick = {
                onGlossaryDelete(glossary)
            }
        ) {
            Icon(
                imageVector = Icons.Default.Delete,
                contentDescription = "Delete Glossary"
            )
        }
    }
}

@Composable
fun glossariesPage(
    languageManager: LanguageManager,
    currentPage: MutableState<String>,
    onProjectClick: () -> Unit,
    onCodeToVerifyClick: () -> Unit
) {
    var glossaries by remember { mutableStateOf(emptyList<Glossary>()) }
    val noFileSnackbarVisibleState = remember { mutableStateOf(false) }

    Column(
        modifier = Modifier.fillMaxSize(),
        verticalArrangement = Arrangement.Center,
        horizontalAlignment = Alignment.CenterHorizontally
    ) {
        Text(languageManager.getSelectGlossaryText(), style = MaterialTheme.typography.h5)

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

        Box(
            modifier = Modifier
                .height(300.dp)
                .width(250.dp)
                .padding(10.dp),
            contentAlignment = Alignment.Center
        ) {
            val scrollState = rememberLazyListState()
            glossaries = loadGlossaries(appState.selectedProject!!)
            if (glossaries.isEmpty()) {
                Text(languageManager.getNoGlossaryText())
            } else {
                LazyColumn(
                    state = scrollState,
                    modifier = Modifier.padding(10.dp),
                    verticalArrangement = Arrangement.spacedBy(10.dp)
                ) {
                    items(glossaries) { glossary ->
                        glossaryItem(
                            glossary = glossary,
                            onGlossarySelected = {
                                appState.selectedGlossary = it
                                currentPage.value = "glossaireDetail"
                            },
                            onGlossaryDelete = {
                                glossaries = glossaries.filterNot { g -> g == it }
                                handleGlossaryDeletion(it)
                            }
                        )
                    }
                }
            }
            VerticalScrollbar(
                modifier = Modifier.align(Alignment.CenterEnd).fillMaxHeight(),
                adapter = rememberScrollbarAdapter(scrollState)
            )
        }

        Spacer(modifier = Modifier.height(16.dp))
        // mettre un texte "ou"
        Text(languageManager.getOuText(), style = MaterialTheme.typography.h5)
        Spacer(modifier = Modifier.height(16.dp))

        Button(
            onClick = {
                currentPage.value = "nouveauGlossaire"
            },
            modifier = Modifier.width(300.dp),
            colors = ButtonDefaults.buttonColors(
                backgroundColor = customRedColor,
                contentColor = Color.White
            )
        ) {
            Text(languageManager.getNewGlossaryText())
        }

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

        Button(
            onClick = {
                currentPage.value = "projects"
            },
            modifier = Modifier.width(250.dp),
            colors = ButtonDefaults.buttonColors(
                backgroundColor = customRedColor,
                contentColor = Color.White
            )
        ) {
            Text(languageManager.getBackText())
        }
    }
    dropdownButtonComponent(
        languageManager = languageManager,
        items = listOf(
            languageManager.getGlossaryText(),
            languageManager.getCodeToVerifyText(),
            languageManager.getCompareText()
        )
    ) { selectedOption ->
        // Handle the selected option
        when (selectedOption) {
            languageManager.getGlossaryText() -> onProjectClick()
            languageManager.getCodeToVerifyText() -> onCodeToVerifyClick()
            languageManager.getCompareText() -> {
                if (mostUsedWordList.isEmpty()) {
                    noFileSnackbarVisibleState.value = true
                    return@dropdownButtonComponent
                } else {
                    currentPage.value = "compareProject"
                }
            }
        }
    }
}

private fun handleGlossaryDeletion(glossary: Glossary) {
    val file = File("${glossaryPath}${appState.selectedProject?.name}/${glossary.jsonFilePath}")
    val deletionResult = file.delete()

    if (deletionResult) {
        println("File deleted successfully.")
    } else {
        println("Error while deleting file.")
    }
}

@OptIn(ExperimentalComposeUiApi::class)
@Composable
fun newGlossary(
    languageManager: LanguageManager,
    currentPage: MutableState<String>,
) {
    val isEmptySnackbarVisibleState = remember { mutableStateOf(false) }
    val containsSpaceSnackbarVisibleState = remember { mutableStateOf(false) }
    val glossaryAlreadyExistsSnackbarVisibleState = remember { mutableStateOf(false) }
    val invalidCharacterSnackbarVisibleState = remember { mutableStateOf(false) }

    var glossaries by remember { mutableStateOf(emptyList<Glossary>()) }

    var nouveauGlossaireName by remember { mutableStateOf("") }

    Column(
        modifier = Modifier.fillMaxSize(),
        verticalArrangement = Arrangement.Center,
        horizontalAlignment = Alignment.CenterHorizontally
    ) {
        Text(languageManager.getNameGlossaryText(), style = MaterialTheme.typography.h5)

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

        TextField(
            value = nouveauGlossaireName,
            singleLine = true,
            onValueChange = { nouveauGlossaireName = it },
            label = { Text("Nom du glossaire") },
            colors = TextFieldDefaults.textFieldColors(
                focusedIndicatorColor = customRedColor,
                unfocusedIndicatorColor = Color.Gray,
                focusedLabelColor = customRedColor
            ),
            modifier = Modifier
                .width(300.dp)
                .fillMaxWidth()
                .onKeyEvent { event ->
                    if (event.key == Key.Enter && event.type == KeyEventType.KeyDown) {
                        when {
                            nouveauGlossaireName.isEmpty() -> {
                                println("Veuillez saisir un nom pour le nouveau glossaire")
                                isEmptySnackbarVisibleState.value = true
                            }
                            nouveauGlossaireName.contains(" ") -> {
                                println("Le nom du glossaire ne doit pas contenir d'espace")
                                containsSpaceSnackbarVisibleState.value = true
                            }
                            glossaries.any { it.name == nouveauGlossaireName } -> {
                                println("Le nom du glossaire existe déjà")
                                glossaryAlreadyExistsSnackbarVisibleState.value = true
                            }
                            !isValidFileName(nouveauGlossaireName) -> {
                                println("Le nom du glossaire contient des caractères non autorisés")
                                invalidCharacterSnackbarVisibleState.value = true
                            }
                            else -> {
                                val newGlossary = Glossary(nouveauGlossaireName, "$nouveauGlossaireName.json")
                                glossaries = glossaries + newGlossary
                                // create new json file
                                val newFile =
                                    File(glossaryPath + (appState.selectedProject?.name) + "/" + newGlossary.jsonFilePath)
                                newFile.createNewFile()
                                // update glossaries list
                                glossaries = loadGlossaries(appState.selectedProject!!)
                                currentPage.value = "glossaires" // Revenir à la liste des glossaires
                            }
                        }
                        true
                    } else {
                        false
                    }
                }
        )

        Button(
            onClick = {
                // Handle the Enter key event by calling the common function
                when {
                    nouveauGlossaireName.isEmpty() -> {
                        println("Veuillez saisir un nom pour le nouveau glossaire")
                        isEmptySnackbarVisibleState.value = true
                    }
                    nouveauGlossaireName.contains(" ") -> {
                        println("Le nom du glossaire ne doit pas contenir d'espace")
                        containsSpaceSnackbarVisibleState.value = true
                    }
                    glossaries.any { it.name == nouveauGlossaireName } -> {
                        println("Le nom du glossaire existe déjà")
                        glossaryAlreadyExistsSnackbarVisibleState.value = true
                    }
                    !isValidFileName(nouveauGlossaireName) -> {
                        println("Le nom du glossaire contient des caractères non autorisés")
                        invalidCharacterSnackbarVisibleState.value = true
                    }
                    else -> {
                        val newGlossary = Glossary(nouveauGlossaireName, "$nouveauGlossaireName.json")
                        glossaries = glossaries + newGlossary
                        // create new json file
                        val newFile =
                            File(glossaryPath + (appState.selectedProject?.name) + "/" + newGlossary.jsonFilePath)
                        newFile.createNewFile()
                        // update glossaries list
                        glossaries = loadGlossaries(appState.selectedProject!!)
                        currentPage.value = "glossaires" // Revenir à la liste des glossaires
                    }
                }
            },
            modifier = Modifier
                .width(200.dp),
            colors = ButtonDefaults.buttonColors(
                backgroundColor = customRedColor,
                contentColor = Color.White
            )
        ) {
            Text("Créer")
        }

        Button(
            onClick = {
                currentPage.value = "glossaires"
            },
            modifier = Modifier
                .width(200.dp),
            colors = ButtonDefaults.buttonColors(
                backgroundColor = customRedColor,
                contentColor = Color.White
            )
        ) {
            Text("Annuler")
        }
    }
}

fun selectFile(extensions: Set<String>, onFileSelected: (String) -> Unit) {

    val fileDialog = FileDialog(frame, "Select a file", FileDialog.LOAD)
    fileDialog.isMultipleMode = true // To enable selecting only one file
    fileDialog.file = "*." + extensions.joinToString(";*.")
    fileDialog.isVisible = true

    val selectedFiles = fileDialog.files

    if (selectedFiles != null) {
        for (file in selectedFiles) {
            println("Selected file: $file")
            // Verify that the file extension is valid
            val fileExtension = File(file.absolutePath).extension.lowercase()
            if (extensions.contains(fileExtension)) {
                println("Opening: $file")
                onFileSelected(file.absolutePath)
            } else {
                println("Invalid file extension.")
            }
        }
    } else {
        println("Open command cancelled by user.")
    }
    frame.dispose()
}


fun selectDirectory(onDirectorySelected: (String) -> Unit) {
    val fileChooser = JFileChooser(FileSystemView.getFileSystemView().homeDirectory)
    fileChooser.fileSelectionMode = JFileChooser.DIRECTORIES_ONLY

    val returnValue = fileChooser.showDialog(null, "Select")
    if (returnValue == JFileChooser.APPROVE_OPTION) {
        val selectedDirectory = fileChooser.selectedFile.absolutePath
        println("Selected directory: $selectedDirectory")
        onDirectorySelected(selectedDirectory)
    } else {
        println("Open command cancelled by user.")
    }
}

fun exportToCSV(glossary: Glossary, csvFilePath: String) {
    val glossary = loadDatasFromFile(glossary.jsonFilePath)
    val csvContent = buildString {
        appendLine("Mot;Description;Contexte principal;Contexte secondaire;Lié à;Synonyme;Antonyme;")
        glossary.forEach { entry ->
            appendLine(
                "${entry.name};${entry.description};${entry.mainContext};" +
                        "${entry.secondaryContext};${entry.relatedTo};${entry.synonymous};${entry.antonym}"
            )
        }
    }
    try {
        FileWriter("$csvFilePath.csv").use { fileWriter ->
            fileWriter.write(csvContent)
        }
        exportedSuccessfully.value = true
    } catch (e: IOException) {
        e.printStackTrace()
    }
}

fun importFile(glossary: Glossary, filePath: String) {
    val fileExtension = File(filePath).extension.lowercase()

    when (fileExtension) {
        "csv" -> {
            importCSVFile(glossary, filePath)
        }

        "xlsx" -> {
            importXLSXFile(glossary, filePath)
        }

        else -> {
            println("Unsupported file format.")
        }
    }
}


fun importCSVFile(glossary : Glossary, filePath: String) {
    val file = File(filePath).readText(Charsets.UTF_8)

    val lines = file.split("\n")
    val header = lines.first().split(";")
    val dataLines = lines.drop(1)

    dataLines.forEach { line ->
        // Check if the line is not empty or blank
        if (line.isNotBlank()) {
            val values = line.replace("\r", "").replace("\n", "").split(";")

            values.forEach { value ->
                println(value)
            }
            val mot = header.zip(values).toMap().toMutableMap()
            try {
                val nouveauWord = Word(
                    name = mot["Mot"]!!,
                    description = mot["Description"]!!,
                    mainContext = mot["Contexte principal"]!!,
                    secondaryContext = mot["Contexte secondaire"]!!,
                    relatedTo = mot["Lié à"]!!,
                    synonymous = mot["Synonyme"]!!,
                    antonym = mot["Antonyme"]!!
                )

                if (mot["Antonyme"] == "\r") {
                    mot["Antonyme"] = ""
                }
                if (mot["Mot"] == null || mot["Mot"] == "") {
                    return
                }
                if (!verifyRequiredFields(mot)) {
                    return
                }
                addWordToGlossary(glossary.jsonFilePath, nouveauWord)
            }catch(e : NullPointerException){
                errorImportation.value = true
            }

        }
        importedSuccessfully.value = true
    }

}


private fun importXLSXFile(glossary: Glossary, cheminFichier: String) {
    val workbook: Workbook
    try {
        FileInputStream(cheminFichier).use { fileInputStream ->
            workbook = XSSFWorkbook(fileInputStream)
        }

        val sheet = workbook.getSheetAt(0) // Assuming the data is in the first sheet

        val headerRow = sheet.getRow(0)
        val header = mutableListOf<String>()
        for (i in 0 until headerRow.lastCellNum) {
            header.add(headerRow.getCell(i).stringCellValue)
        }

        val dataLines = mutableListOf<Map<String, String>>()

        for (i in 1 until sheet.physicalNumberOfRows) {
            val currentRow = sheet.getRow(i)
            val data = mutableMapOf<String, String>()

            for (j in 0 until currentRow.lastCellNum) {
                val cell = currentRow.getCell(j)
                val cellValue = when (cell.cellType) {
                    CellType.STRING -> cell.stringCellValue
                    CellType.NUMERIC -> cell.numericCellValue.toString()
                    else -> ""
                }
                data[header[j]] = cellValue
            }

            dataLines.add(data)
        }

        dataLines.forEach { line ->
            // Check if the line is not empty or blank
            if (line.isNotEmpty()) {
                // Process each line as needed
                val newWord = Word(
                    name = line["Mot"] ?: "",
                    description = line["Description"] ?: "",
                    mainContext = line["Contexte principal"] ?: "",
                    secondaryContext = line["Contexte secondaire"] ?: "",
                    relatedTo = line["Lié à"] ?: "",
                    synonymous = line["Synonyme"] ?: "",
                    antonym = line["Antonyme"] ?: ""
                )

                if (newWord.name.isNotBlank() && verifyRequiredFields(line)) {
                    addWordToGlossary(glossary.jsonFilePath, newWord)
                }
            }
        }
    } catch (e: IOException) {
        e.printStackTrace()
    }
}

fun verifyRequiredFields(mot: Map<String, String>): Boolean {
    //Verify that the required fields are present
    val requiredFields = listOf(
        "Mot",
        "Description",
        "Contexte principal",
        "Contexte secondaire",
        "Lié à",
        "Synonyme",
        "Antonyme"
    )

    val motKeys = mot.keys.map { it.trim() }

    motKeys.forEach { key ->
        if (!requiredFields.contains(key)) {
            println("Le champ $key n'est pas reconnu")
            return false
        }
    }

    return true

}