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

import android.app.Application
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.FlowRow
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.lerp
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
import androidx.navigation.NavController
import eu.gaudian.translator.R
import eu.gaudian.translator.model.Language
import eu.gaudian.translator.model.VocabularyItem
import eu.gaudian.translator.utils.Log
import eu.gaudian.translator.utils.findActivity
import eu.gaudian.translator.view.composable.AppIcons
import eu.gaudian.translator.view.composable.SecondaryButton
import eu.gaudian.translator.viewmodel.DictionaryViewModel
import eu.gaudian.translator.viewmodel.LanguageViewModel
import eu.gaudian.translator.viewmodel.VocabularyViewModel
import kotlinx.coroutines.launch
import okhttp3.internal.platform.PlatformRegistry.applicationContext
import kotlin.system.measureTimeMillis


data class SynonymDisplayState(
    val synonym: VocabularyItem,
    val language: Language,
    val alreadyInRepository: Boolean,
    val proximity: Int?
)

@Composable
fun AdditionalContentBottomSheet(
    vocabularyItemId: Int,
    term: String, // "first" or "second"
    navController: NavController,
) {
    val activity = LocalContext.current.findActivity()

    val vocabularyViewModel: VocabularyViewModel = hiltViewModel(viewModelStoreOwner = activity)
    val languageViewModel: LanguageViewModel = hiltViewModel(viewModelStoreOwner = activity)
    val dictionaryViewModel: DictionaryViewModel = hiltViewModel(viewModelStoreOwner = activity)
    val coroutineScope = rememberCoroutineScope()

    // Get the vocabulary item
    val vocabularyItem by vocabularyViewModel.getVocabularyItemFlow(vocabularyItemId)
        .collectAsState(initial = null)

    val item = vocabularyItem ?: return

    // Get languages
    val languageFirst by languageViewModel.getLanguageByIdFlow(item.languageFirstId ?: 0)
        .collectAsState(initial = null)
    val languageSecond by languageViewModel.getLanguageByIdFlow(item.languageSecondId ?: 0)
        .collectAsState(initial = null)

    // State for synonyms and examples
    var synonyms by remember(vocabularyItemId, term) { mutableStateOf<List<SynonymDisplayState>?>(null) }
    var example by remember(vocabularyItemId, term) { mutableStateOf<Pair<String, String>?>(null) }

    // Loading states for refresh operations
    var synonymsLoading by remember { mutableStateOf(false) }
    var exampleLoading by remember { mutableStateOf(false) }

    // Determine which word and language to use
    val isFirst = term == "first"
    val word = if (isFirst) item.wordFirst else item.wordSecond
    val language = if (isFirst) languageFirst else languageSecond

    // Handle dictionary navigation
    val handleMoveToDictionary: () -> Unit = {
        if (language != null) {
            coroutineScope.launch {
                @Suppress("HardCodedStringLiteral")
                Log.i("handleMoveToDictionary","handleMoveToDictionary performed")
                dictionaryViewModel.performSearch(
                    query = word,
                    language = language,
                    regenerate = false
                )
            }
        }
    }

    val entryToNavigate by dictionaryViewModel.navigateToEntry.collectAsState()
    LaunchedEffect(key1 = entryToNavigate) {
        entryToNavigate?.let { entry ->
            // Set flag indicating navigation is from external source (not DictionaryResultScreen)
            dictionaryViewModel.setNavigatingFromDictionaryResult(false)
            // Clear the navigation event immediately to prevent DictionaryResultScreen from handling it
            dictionaryViewModel.onNavigationDone()
            @Suppress("HardCodedStringLiteral")
            navController.navigate("dictionary_result/${entry.id}") {
                // Clear the back stack up to the dictionary_result destination to prevent double navigation
                popUpTo("dictionary_result") { inclusive = false }
                launchSingleTop = true
            }
        }
    }

    val refreshSynonyms: () -> Unit = {
        if (language != null) {
            coroutineScope.launch {
                synonymsLoading = true
                measureTimeMillis {
                    val rawSynonymData = vocabularyViewModel.getSynonymsForItem(
                        vocabularyItemId = item.id,
                        isForFirstWord = isFirst
                    )
                    val sortedSynonymData = rawSynonymData.sortedByDescending { it.proximity ?: 101 }

                    if (sortedSynonymData.isNotEmpty()) {
                        val rawItems = sortedSynonymData.map { it.item }
                        val existenceFlags = vocabularyViewModel.findDuplicates(rawItems)
                        synonyms = sortedSynonymData.mapIndexed { index, synonymData ->
                            SynonymDisplayState(
                                synonym = synonymData.item,
                                language = language,
                                alreadyInRepository = existenceFlags[index],
                                proximity = synonymData.proximity
                            )
                        }
                    } else {
                        synonyms = emptyList()
                    }
                }
                synonymsLoading = false
            }
        }
    }

    val refreshExample: () -> Unit = {
        coroutineScope.launch {
            exampleLoading = true
            measureTimeMillis {
                example = vocabularyViewModel.getExampleForItem(
                    item.id,
                    isFirstWord = isFirst,
                    languageFirst = languageFirst,
                    languageSecond = languageSecond
                )
            }
            exampleLoading = false
        }
    }

    // Load data when component is first displayed
    LaunchedEffect(vocabularyItemId, term) {
        refreshExample()
    }

    // Load synonyms when language becomes available
    LaunchedEffect(language) {
        if (language != null) {
            refreshSynonyms()
        }
    }

    // Handle synonym addition
    val handleSynonymAdded: () -> Unit = {
        refreshSynonyms()
    }

    // Handle example reload
    val handleReloadExample: () -> Unit = {
        refreshExample()
    }
    Column(
        modifier = Modifier
            .fillMaxSize()
            .padding(16.dp)
            .verticalScroll(rememberScrollState())
    ) {
        Text(
            text = word,
            style = MaterialTheme.typography.headlineMedium,
            fontWeight = FontWeight.Bold,
            modifier = Modifier.padding(bottom = 16.dp)
        )

        if (language != null) {
            Text(
                text = language.name,
                style = MaterialTheme.typography.titleMedium,
                modifier = Modifier.padding(bottom = 16.dp)
            )
        }

        ExampleSentencesDisplay(exampleSentence = example, loading = exampleLoading, onReload = handleReloadExample)

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

        SynonymsDisplay(
            synonyms = synonyms,
            loading = synonymsLoading,
            onSynonymAdded = handleSynonymAdded,
            onReload = refreshSynonyms
        )

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

        MoveToDictionaryButton(onClick = handleMoveToDictionary)
    }
}

@Preview
@Composable
fun AdditionalContentBottomSheetPreview() {

    AdditionalContentBottomSheet(
        vocabularyItemId = 1,
        term = "first",
        navController = NavController(applicationContext as Application)
    )
}

@Composable
private fun ExampleSentencesDisplay(
    exampleSentence: Pair<String, String>?,
    loading: Boolean,
    onReload: () -> Unit,
) {
    Column {
        Row(
            modifier = Modifier.fillMaxWidth(),
            horizontalArrangement = Arrangement.SpaceBetween,
            verticalAlignment = Alignment.CenterVertically
        ) {
            Text(
                text = stringResource(R.string.example),
                style = MaterialTheme.typography.titleMedium,
                fontWeight = FontWeight.Bold,
                modifier = Modifier.padding(bottom = 0.dp)
            )
            IconButton(onClick = onReload) {
                Icon(
                    modifier = Modifier.padding(0.dp),
                    imageVector = AppIcons.Refresh,
                    contentDescription = stringResource(R.string.label_reload)
                )
            }
        }

        if (loading || exampleSentence == null) {
            Box(
                modifier = Modifier
                    .fillMaxWidth()
                    .padding(vertical = 2.dp),
                contentAlignment = Alignment.Center
            ) {
                CircularProgressIndicator()
            }
        } else {
            Text(
                text = "\"${exampleSentence.first.trim()}\"",
                style = MaterialTheme.typography.bodyMedium,
            )
            Spacer(Modifier.height(4.dp))
            Text(
                text = "\"${exampleSentence.second.trim()}\"",
                style = MaterialTheme.typography.bodyMedium,
            )
        }
    }
}

@Preview(showBackground = true)
@Composable
private fun ExampleSentencesDisplayLoadingPreview() {
    ExampleSentencesDisplay(exampleSentence = null, loading = false, onReload = {})
}

@Suppress("HardCodedStringLiteral")
@Preview(showBackground = true)
@Composable
private fun ExampleSentencesDisplayLoadedPreview() {
    ExampleSentencesDisplay(
        exampleSentence = Pair("This is an example sentence.", "Dies ist ein Beispielsatz."),
        loading = false,
        onReload = {}
    )
}



@Composable
private fun SynonymsDisplay(
    synonyms: List<SynonymDisplayState>?,
    loading: Boolean,
    onSynonymAdded: () -> Unit,
    onReload: () -> Unit,
) {

    val activity = LocalContext.current.findActivity()
    val vocabularyViewModel: VocabularyViewModel = hiltViewModel(viewModelStoreOwner = activity)
    Column {
        Row(
            modifier = Modifier.fillMaxWidth(),
            horizontalArrangement = Arrangement.SpaceBetween,
            verticalAlignment = Alignment.CenterVertically
        ) {
            Text(
                text = stringResource(R.string.synonyms),
                style = MaterialTheme.typography.titleMedium,
                fontWeight = FontWeight.Bold
            )
            IconButton(onClick = onReload) {
                Icon(
                    imageVector = AppIcons.Refresh,
                    contentDescription = stringResource(R.string.label_reload)
                )
            }
        }
        Spacer(Modifier.height(4.dp))

        if (loading || synonyms == null) {
            Box(
                modifier = Modifier
                    .fillMaxWidth()
                    .padding(vertical = 16.dp),
                contentAlignment = Alignment.Center
            ) {
                CircularProgressIndicator()
            }
            return
        }

        if (synonyms.isNotEmpty()) {
            val coroutineScope = rememberCoroutineScope()
            var locallyAddedSynonyms by remember(synonyms) { mutableStateOf(emptySet<VocabularyItem>()) }

            FlowRow(
                modifier = Modifier.fillMaxWidth(),
            ) {
                synonyms.forEach { state ->
                    val isDisplayedAsAdded = state.alreadyInRepository || locallyAddedSynonyms.contains(state.synonym)

                    SynonymChip(
                        state = state,
                        isDisplayedAsAdded = isDisplayedAsAdded,
                        onAddClick = { itemToAdd ->
                            coroutineScope.launch {
                                vocabularyViewModel.addVocabularyItems(listOf(itemToAdd))
                                locallyAddedSynonyms = locallyAddedSynonyms + itemToAdd
                                onSynonymAdded()
                            }
                        }
                    )
                }
            }
        }
    }
}

@Preview(showBackground = true)
@Composable
private fun SynonymsDisplayLoadingPreview() {
    // This preview doesn't have a real VocabularyViewModel, so actions will not work.
    SynonymsDisplay(synonyms = null, loading = false, onSynonymAdded = {}, onReload = {})
}

@Suppress("HardCodedStringLiteral")
@Preview(showBackground = true)
@Composable
private fun SynonymsDisplayLoadedPreview() {
    val language = Language(code = "en", region = "US", nameResId = 1, name = "English", englishName = "English")
    val synonyms = listOf(
        SynonymDisplayState(
            synonym = VocabularyItem(1, 1, 2, "similar", "ähnlich", null, null, null, null),
            language = language,
            alreadyInRepository = false,
            proximity = 95
        ),
        SynonymDisplayState(
            synonym = VocabularyItem(2, 1, 2, "alike", "gleich", null, null, null, null),
            language = language,
            alreadyInRepository = true,
            proximity = 80
        ),
        SynonymDisplayState(
            synonym = VocabularyItem(3, 1, 2, "comparable", "vergleichbar", null, null, null, null),
            language = language,
            alreadyInRepository = false,
            proximity = null
        )
    )
    SynonymsDisplay(synonyms = synonyms, loading = false, onSynonymAdded = {}, onReload = {})
}

@Composable
private fun MoveToDictionaryButton(onClick: () -> Unit) {

    SecondaryButton(
        modifier = Modifier.fillMaxWidth(),
        onClick = onClick,
        text = stringResource(R.string.label_show_dictionary_entry),
        icon = AppIcons.ArrowForward
    )



}

@Preview
@Composable
private fun MoveToDictionaryButtonPreview() {

    MoveToDictionaryButton(onClick = {})

}



@Composable
private fun SynonymChip(
    state: SynonymDisplayState,
    isDisplayedAsAdded: Boolean,
    onAddClick: (VocabularyItem) -> Unit,
) {
    val text = if (state.language.nameResId == state.synonym.languageFirstId) {
        state.synonym.wordFirst
    } else {
        state.synonym.wordSecond
    }

    val displayText = if (state.proximity != null) {
        "$text (${state.proximity}%)"
    } else {
        text
    }

    val icon = if (isDisplayedAsAdded) AppIcons.Check else AppIcons.Add

    val backgroundColor = when {
        isDisplayedAsAdded -> MaterialTheme.colorScheme.secondaryContainer
        state.proximity != null -> {
            val fraction = (state.proximity / 100f).coerceIn(0f, 1f)
            lerp(
                start = MaterialTheme.colorScheme.surfaceVariant,
                stop = MaterialTheme.colorScheme.primaryContainer,
                fraction = fraction
            )
        }
        else -> MaterialTheme.colorScheme.primaryContainer
    }

    val contentColor = when {
        isDisplayedAsAdded -> MaterialTheme.colorScheme.onSecondaryContainer
        state.proximity != null -> {
            val fraction = (state.proximity / 100f).coerceIn(0f, 1f)
            lerp(
                start = MaterialTheme.colorScheme.onSurfaceVariant,
                stop = MaterialTheme.colorScheme.onPrimaryContainer,
                fraction = fraction
            )
        }
        else -> MaterialTheme.colorScheme.onPrimaryContainer
    }

    val clickModifier = if (isDisplayedAsAdded) {
        Modifier
    } else {
        Modifier.clickable { onAddClick(state.synonym) }
    }

    Surface(
        modifier = Modifier
            .padding(4.dp)
            .then(clickModifier),
        shape = RoundedCornerShape(16.dp),
        color = backgroundColor,
        contentColor = contentColor,
        tonalElevation = 2.dp
    ) {
        Row(
            modifier = Modifier.padding(horizontal = 6.dp, vertical = 4.dp),
            verticalAlignment = Alignment.CenterVertically,
            horizontalArrangement = Arrangement.spacedBy(6.dp)
        ) {
            Icon(
                imageVector = icon,
                contentDescription = if (isDisplayedAsAdded) stringResource(R.string.synonym_exists) else stringResource(
                    R.string.label_add_synonym
                )
            )
            Text(text = displayText, style = MaterialTheme.typography.bodyMedium)
        }
    }
}

@Suppress("HardCodedStringLiteral")
@Preview
@Composable
private fun SynonymChipNotAddedPreview() {
    val language = Language(code = "en", region = "US", nameResId = 1, name = "English", englishName = "English")
    val state = SynonymDisplayState(
        synonym = VocabularyItem(1, 1, 2, "example", "beispiel", null, null, null, null),
        language = language,
        alreadyInRepository = false,
        proximity = 85
    )
    SynonymChip(
        state = state,
        isDisplayedAsAdded = false,
        onAddClick = {}
    )
}

@Suppress("HardCodedStringLiteral")
@Preview
@Composable
private fun SynonymChipAddedPreview() {
    val language = Language(code = "en", region = "US", nameResId = 1, name = "English", englishName = "English")
    val state = SynonymDisplayState(
        synonym = VocabularyItem(1, 1, 2, "example", "beispiel", null, null, null, null),
        language = language,
        alreadyInRepository = true,
        proximity = 90
    )
    SynonymChip(
        state = state,
        isDisplayedAsAdded = true,
        onAddClick = {}
    )
}
