@file:Suppress("HardCodedStringLiteral")

package eu.gaudian.translator.view.vocabulary.card

import android.annotation.SuppressLint
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.Checkbox
import androidx.compose.material3.DropdownMenuItem
import androidx.compose.material3.ExposedDropdownMenuAnchorType
import androidx.compose.material3.ExposedDropdownMenuBox
import androidx.compose.material3.ExposedDropdownMenuDefaults
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.blur
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontStyle
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
import eu.gaudian.translator.R
import eu.gaudian.translator.model.Language
import eu.gaudian.translator.model.grammar.CategoryConfig
import eu.gaudian.translator.model.grammar.FieldConfig
import eu.gaudian.translator.model.grammar.GrammaticalFeature
import eu.gaudian.translator.model.grammar.LanguageConfig
import eu.gaudian.translator.model.grammar.formatGrammarDetails
import eu.gaudian.translator.utils.Log
import eu.gaudian.translator.utils.findActivity
import eu.gaudian.translator.view.composable.AppDialog
import eu.gaudian.translator.view.composable.AppOutlinedTextField
import eu.gaudian.translator.view.composable.DialogButton
import eu.gaudian.translator.viewmodel.LanguageConfigViewModel

@Composable
internal fun GrammarDetailsText(
    details: GrammaticalFeature?,
    language: Language?,
    isRevealed: Boolean
) {
    Log.d("GrammarComponents", "GrammarDetailsText called with details: $details, language: $language, isRevealed: $isRevealed")

    val activity = LocalContext.current.findActivity()
    val configViewModel: LanguageConfigViewModel = hiltViewModel(activity)
    val allConfigs by configViewModel.configs.collectAsState()
    val languageConfig = language?.code?.let { allConfigs[it] }
    val categoryConfig = details?.category?.let { languageConfig?.categories?.get(it) }

    val propertiesString = remember(details, categoryConfig) {
        if (details == null) {
            ""
        } else {
            formatGrammarDetails(details, categoryConfig)
        }
    }

    Log.d("GrammarComponents", "Properties string: '$propertiesString'")
    
    if (propertiesString.isNotEmpty()) {
        Text(
            text = propertiesString,
            style = MaterialTheme.typography.bodyLarge.copy(fontStyle = FontStyle.Italic),
            color = MaterialTheme.colorScheme.onSurface.copy(alpha = 0.7f),
            modifier = Modifier.blur(if (!isRevealed) 10.dp else 0.dp)
        )
    }
}

@Composable
internal fun GrammarEditDialog(
    feature: GrammaticalFeature?,
    language: Language,
    onDismiss: () -> Unit,
    onSave: (GrammaticalFeature?) -> Unit
) {
    Log.d("GrammarComponents", "GrammarEditDialog called with feature: $feature, language: $language")

    val activity = LocalContext.current.findActivity()
    val configViewModel: LanguageConfigViewModel = hiltViewModel(activity)
    val allConfigs by configViewModel.configs.collectAsState()
    val languageConfig = allConfigs[language.code]
    
    Log.d("GrammarComponents", "Language config found: ${languageConfig != null}")

    var selectedCategoryKey by remember { mutableStateOf(feature?.category) }
    var properties by remember { mutableStateOf(feature?.properties ?: emptyMap()) }
    
    Log.d("GrammarComponents", "Initial selectedCategoryKey: $selectedCategoryKey, properties: $properties")

    AppDialog(onDismissRequest = onDismiss, title = {Text(
        text = stringResource(R.string.edit_features_for, language.name),
    )}) {
            Column(modifier = Modifier.padding(16.dp)) {

                if (languageConfig == null) {
                    Text(stringResource(R.string.no_grammar_configuration_found_for_this_language))
                } else {
                    GuidedEditTabContent(
                        languageConfig = languageConfig,
                        selectedCategoryKey = selectedCategoryKey,
                        onCategoryChange = { newCategoryKey ->
                            selectedCategoryKey = newCategoryKey
                            properties = emptyMap()
                        },
                        selectedProperties = properties,
                        onPropertiesChange = { newProperties ->
                            properties = newProperties
                        }
                    )
                }

                Row(
                    modifier = Modifier.fillMaxWidth().padding(0.dp),
                    verticalAlignment = Alignment.CenterVertically
                ) {
                        TextButton(
                            onClick = { onSave(null) },
                            colors = ButtonDefaults.textButtonColors(contentColor = MaterialTheme.colorScheme.error)
                        ) {
                            Text(stringResource(R.string.label_delete))
                        }
                }

                Spacer(Modifier.height(24.dp))

                Row(
                    modifier = Modifier.fillMaxWidth().padding(0.dp),
                    verticalAlignment = Alignment.CenterVertically
                ) {

                    TextButton(onClick = onDismiss) {
                            Text(stringResource(R.string.label_cancel))
                        }
                        DialogButton(
                            onClick = {
                                selectedCategoryKey?.let {
                                    onSave(GrammaticalFeature(category = it, properties = properties))
                                }
                            },
                            enabled = selectedCategoryKey != null,
                            text = stringResource(R.string.label_save)

                        )
                }
            }
    }
}

@Composable
private fun GuidedEditTabContent(
    languageConfig: LanguageConfig,
    selectedCategoryKey: String?,
    onCategoryChange: (String) -> Unit,
    selectedProperties: Map<String, String>,
    onPropertiesChange: (Map<String, String>) -> Unit
) {
    Log.d("GrammarComponents", "GuidedEditTabContent called with selectedCategoryKey: $selectedCategoryKey, selectedProperties: $selectedProperties")
    
    var isCategoryDropdownExpanded by remember { mutableStateOf(false) }
    val categories = languageConfig.categories.entries.toList()
    val selectedCategoryConfig = selectedCategoryKey?.let { languageConfig.categories[it] }
    
    Log.d("GrammarComponents", "Categories count: ${categories.size}, selectedCategoryConfig: $selectedCategoryConfig")

    Column {
        Log.d("GrammarComponents", "Column with verticalScroll modifier created")
        ExposedDropdownMenuBox(
            expanded = isCategoryDropdownExpanded,
            onExpandedChange = { isCategoryDropdownExpanded = !isCategoryDropdownExpanded }
        ) {
            AppOutlinedTextField(
                modifier = Modifier
                    .menuAnchor(ExposedDropdownMenuAnchorType.PrimaryEditable, enabled = true)
                    .fillMaxWidth(),
                readOnly = true, // value is from a dropdown
                value = selectedCategoryConfig?.display_key?.let { resolveStringResource(it) } ?: stringResource(R.string.text_select_category),
                onValueChange = {}, // readOnly, so no-op
                label = { Text(stringResource(R.string.word_type)) },
                trailingIcon = { ExposedDropdownMenuDefaults.TrailingIcon(expanded = isCategoryDropdownExpanded) },
            )
            ExposedDropdownMenu(
                expanded = isCategoryDropdownExpanded,
                onDismissRequest = { isCategoryDropdownExpanded = false }
            ) {
                categories.forEach { (key, config) ->
                    DropdownMenuItem(
                        text = { Text(resolveStringResource(config.display_key)) },
                        onClick = {
                            onCategoryChange(key)
                            isCategoryDropdownExpanded = false
                        }
                    )
                }
            }
        }

        Spacer(Modifier.height(16.dp))

        selectedCategoryConfig?.fields?.forEach { fieldConfig ->
            DynamicField(
                fieldConfig = fieldConfig,
                currentValue = selectedProperties[fieldConfig.key],
                onValueChange = { newValue ->
                    val newProps = selectedProperties.toMutableMap()
                    if (newValue == null) {
                        newProps.remove(fieldConfig.key)
                    } else {
                        newProps[fieldConfig.key] = newValue
                    }
                    onPropertiesChange(newProps)
                }
            )
            Spacer(Modifier.height(8.dp))
        }
    }
}

@Suppress("HardCodedStringLiteral")
@Composable
private fun DynamicField(
    fieldConfig: FieldConfig,
    currentValue: String?,
    onValueChange: (String?) -> Unit
) {
    Log.d("GrammarComponents", "DynamicField called with fieldConfig: ${fieldConfig.key}, type: ${fieldConfig.type}, currentValue: $currentValue")
    
    val label = resolveStringResource(fieldConfig.display_key)
    
    Log.d("GrammarComponents", "Resolved label: $label")

    when (fieldConfig.type) {
        "text" -> {
            AppOutlinedTextField(
                value = currentValue ?: "",
                onValueChange = { onValueChange(it.ifEmpty { null }) },
                label = { Text(label) },
                modifier = Modifier.fillMaxWidth()
            )
        }
        "enum" -> {
            var isExpanded by remember { mutableStateOf(false) }
            ExposedDropdownMenuBox(
                expanded = isExpanded,
                onExpandedChange = {
                    isExpanded = !isExpanded
                }
            ) {
                AppOutlinedTextField(
                    modifier = Modifier
                        .menuAnchor(ExposedDropdownMenuAnchorType.PrimaryEditable, enabled = true)
                        .fillMaxWidth(),
                    readOnly = true,
                    value = currentValue?.let { resolveStringResource(it) } ?: "",
                    onValueChange = {},
                    label = { Text(label) },
                    trailingIcon = { ExposedDropdownMenuDefaults.TrailingIcon(expanded = isExpanded) },
                )
                ExposedDropdownMenu(
                    expanded = isExpanded,
                    onDismissRequest = { isExpanded = false }
                ) {
                    fieldConfig.options?.forEach { optionKey ->
                        DropdownMenuItem(
                            text = { Text(resolveStringResource(optionKey)) },
                            onClick = {
                                onValueChange(optionKey)
                                isExpanded = false
                            }
                        )
                    }
                }
            }
        }
        "boolean" -> {
            Row(
                verticalAlignment = Alignment.CenterVertically,
                modifier = Modifier
                    .fillMaxWidth()
                    .clickable { onValueChange((!(currentValue?.toBoolean() ?: false)).toString()) }
            ) {
                Checkbox(
                    checked = currentValue?.toBoolean() ?: false,
                    onCheckedChange = { onValueChange(it.toString()) }
                )
                Spacer(Modifier.width(8.dp))
                Text(label)
            }
        }
    }
}

/**
 * A map to associate string keys from the grammar configuration with their corresponding
 * Android string resource IDs. This avoids the use of `getIdentifier` which is inefficient
 * and discouraged. This approach is much faster and allows for compile-time verification.
 */
@Suppress("HardCodedStringLiteral")
private val stringResourceMap = mapOf(
    "noun" to R.string.label_noun,
    "verb" to R.string.label_verb,
    "adjective" to R.string.label_adjective,
    "adverb" to R.string.label_adverb,
    "pronoun" to R.string.label_pronoun,
    "preposition" to R.string.label_preposition,
    "conjunction" to R.string.label_conjunction,
    "interjection" to R.string.label_interjection,
    "article" to R.string.label_article,
    "gender" to R.string.label_gender,
    "masculine" to R.string.label_masculine,
    "feminine" to R.string.label_feminine,
    "neuter" to R.string.label_neuter,
    "common" to R.string.label_common,
    "plural" to R.string.label_plural,
    "tense" to R.string.label_tense,
    "present" to R.string.present,
    "past" to R.string.past,
    "future" to R.string.future,
    "mood" to R.string.mood,
    "indicative" to R.string.indicative,
    "subjunctive" to R.string.subjunctive,
    "imperative" to R.string.imperative,
    "word_type" to R.string.word_type
)

@SuppressLint("LocalContextResourcesRead")
@Composable
private fun resolveStringResource(key: String): String {
    // Using a map is more efficient than reflection with getIdentifier,
    // as it avoids runtime lookups and allows for better build optimizations.
    val resourceId = stringResourceMap[key]
    return if (resourceId != null) {
        stringResource(id = resourceId)
    } else {
        // Fallback for keys not in the map, useful for development or dynamic keys.
        // The remember call here prevents recalculating the formatted string on every recomposition.
        remember(key) {
            key.replace('_', ' ').replaceFirstChar { if (it.isLowerCase()) it.titlecase() else it.toString() }
        }
    }
}

@Suppress("HardCodedStringLiteral")
@Preview
@Composable
fun GrammarDetailsTextPreview() {
    val details = GrammaticalFeature(
        category = "noun",
        properties = mapOf("gender" to "masculine", "plural" to "die Männer")
    )
    val language = Language(
        code = "de",
        region = "DE",
        nameResId = 0,
        name = "German",
        englishName = "German"
    )
    GrammarDetailsText(details = details, language = language, isRevealed = true)
}

@Suppress("HardCodedStringLiteral")
@Preview
@Composable
fun GrammarDetailsTextBlurredPreview() {
    val details = GrammaticalFeature(
        category = "noun",
        properties = mapOf("gender" to "masculine", "plural" to "die Männer")
    )
    val language = Language(
        code = "de",
        region = "DE",
        nameResId = 0,
        name = "German",
        englishName = "German"
    )
    GrammarDetailsText(details = details, language = language, isRevealed = false)
}

@Suppress("HardCodedStringLiteral")
@Preview
@Composable
fun GrammarEditDialogPreview() {
    val language = Language(
        code = "de",
        region = "DE",
        nameResId = 0,
        name = "German",
        englishName = "German"
    )
    val feature = GrammaticalFeature(
        category = "noun",
        properties = mapOf("gender" to "masculine")
    )
    GrammarEditDialog(
        feature = feature,
        language = language,
        onDismiss = {},
        onSave = {}
    )
}

@Suppress("HardCodedStringLiteral")
@Preview
@Composable
fun GuidedEditTabContentPreview() {
    val languageConfig = LanguageConfig(
        language_code = "de",
        categories = mapOf(
            "noun" to CategoryConfig(
                display_key = "noun",
                fields = listOf(
                    FieldConfig(
                        "gender",
                        "gender",
                        "enum",
                        listOf("masculine", "feminine", "neuter")
                    ),
                    FieldConfig("plural", "plural", "text")
                )
            ),
            "verb" to CategoryConfig(
                display_key = "verb",
                fields = listOf(
                    FieldConfig("tense", "tense", "enum", listOf("present", "past"))
                )
            )
        )
    )
    GuidedEditTabContent(
        languageConfig = languageConfig,
        selectedCategoryKey = "noun",
        onCategoryChange = {},
        selectedProperties = mapOf("gender" to "masculine"),
        onPropertiesChange = {}
    )
}

@Suppress("HardCodedStringLiteral")
@Preview
@Composable
fun DynamicFieldTextPreview() {
    val fieldConfig = FieldConfig(
        key = "plural",
        display_key = "Plural form",
        type = "text"
    )
    DynamicField(
        fieldConfig = fieldConfig,
        currentValue = "die Wörter",
        onValueChange = {}
    )
}

@Suppress("HardCodedStringLiteral")
@Preview
@Composable
fun DynamicFieldEnumPreview() {
    val fieldConfig = FieldConfig(
        key = "gender",
        display_key = "Gender",
        type = "enum",
        options = listOf("masculine", "feminine", "neuter")
    )
    DynamicField(
        fieldConfig = fieldConfig,
        currentValue = "masculine",
        onValueChange = {}
    )
}

@Suppress("HardCodedStringLiteral")
@Preview
@Composable
fun DynamicFieldBooleanPreview() {
    val fieldConfig = FieldConfig(
        key = "is_strong",
        display_key = "Is strong verb?",
        type = "boolean"
    )
    DynamicField(
        fieldConfig = fieldConfig,
        currentValue = "true",
        onValueChange = {}
    )
}

@Suppress("HardCodedStringLiteral")
@Preview
@Composable
fun ResolveStringResourceWithResourceIdPreview() {
    // This preview depends on having a real resource. It might not render correctly in all cases.
    // Let's assume R.string.word_type exists and its key is "word_type".
    // In a real app, this would resolve to "Word type".
    Text(resolveStringResource("word_type"))
}

@Suppress("HardCodedStringLiteral")
@Preview
@Composable
fun ResolveStringResourceWithKeyFallbackPreview() {
    // This tests the fallback mechanism when a resource ID is not found.
    Text(resolveStringResource("a_made_up_key"))
}