package eu.gaudian.translator.view.dictionary

import android.content.Context
import androidx.annotation.StringRes
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
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.Modifier
import androidx.compose.ui.graphics.vector.ImageVector
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontStyle
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.DictionaryEntry
import eu.gaudian.translator.model.Language
import eu.gaudian.translator.model.repository.DictionaryWordEntry
import eu.gaudian.translator.utils.TextToSpeechHelper
import eu.gaudian.translator.utils.findActivity
import eu.gaudian.translator.view.composable.AppFabMenu
import eu.gaudian.translator.view.composable.AppIcons
import eu.gaudian.translator.view.composable.AppScaffold
import eu.gaudian.translator.view.composable.AppTopAppBar
import eu.gaudian.translator.view.composable.FabMenuItem
import eu.gaudian.translator.view.composable.TabItem
import eu.gaudian.translator.view.composable.TabbedTopAppBar
import eu.gaudian.translator.view.dialogs.AddVocabularyDialog
import eu.gaudian.translator.viewmodel.DictionaryViewModel
import eu.gaudian.translator.viewmodel.LanguageViewModel
import eu.gaudian.translator.viewmodel.SettingsViewModel
import kotlinx.coroutines.launch

enum class DictionaryResultTab(
    @param:StringRes val titleRes: Int,
    val icon: ImageVector
) {
    AI(R.string.tab_ai_definition, AppIcons.Robo),
    Local(R.string.tab_downloaded, AppIcons.Download)
}

data class DictionaryTabUi(
    val type: DictionaryResultTab,
    override val title: String,
    override val icon: ImageVector
) : TabItem

@Composable
fun DictionaryResultScreen(
    navController: NavController,
    entryId: Int,
) {
    val activity = LocalContext.current.findActivity()
    val dictionaryViewModel: DictionaryViewModel = hiltViewModel(viewModelStoreOwner = activity)
    val languageViewModel: LanguageViewModel = hiltViewModel(viewModelStoreOwner = activity)

    val settingsViewModel: SettingsViewModel = hiltViewModel(viewModelStoreOwner = activity)

    // State Collection
    val searchHistory by dictionaryViewModel.searchHistoryEntries.collectAsState()
    val currentEntry = remember(searchHistory, entryId) { searchHistory.find { it.id == entryId } }
    val isDeveloperModeEnabled by settingsViewModel.isDeveloperModeEnabled.collectAsState()
    val developerEntry by dictionaryViewModel.developerCurrentEntry.collectAsState()
    val allLanguages by languageViewModel.allLanguages.collectAsState()
    val entryToNavigate by dictionaryViewModel.navigateToEntry.collectAsState()
    val generatingEntryIds by dictionaryViewModel.generatingEntryIds.collectAsState()
    val breadcrumbs by dictionaryViewModel.breadcrumbs.collectAsState()

    // Using ViewModel's StateFlows for entryData and localEntries
    val entryData by dictionaryViewModel.currentEntryData.collectAsState()
    val isTtsAvailable by dictionaryViewModel.isTtsAvailable.collectAsState()
    val localEntries by dictionaryViewModel.localEntries.collectAsState()

    var showAddVocabularyDialog by remember { mutableStateOf(false) }

    val context = LocalContext.current
    val scope = rememberCoroutineScope()

    // Update entryData using ViewModel's method
    LaunchedEffect(currentEntry) {
        if (currentEntry != null) {
            val language = languageViewModel.getLanguageById(currentEntry.languageCode)
            val ttsAvailable = TextToSpeechHelper.isPlayable(context, language)
            dictionaryViewModel.updateCurrentEntryData(currentEntry, language, ttsAvailable)
        }
    }

    // Update breadcrumbs using ViewModel's method
    var lastBreadcrumbEntryId by remember { mutableStateOf<Int?>(null) }
    LaunchedEffect(entryData) {
        entryData?.let { data ->
            if (data.entry.id != lastBreadcrumbEntryId) {
                lastBreadcrumbEntryId = data.entry.id
                dictionaryViewModel.updateBreadcrumbs(data.entry)
            }
        }
    }

    // Handle Entry ID direct lookup using ViewModel
    LaunchedEffect(entryId) {
        val entry = dictionaryViewModel.getDictionaryEntryById(entryId)
        if (entry != null) {
            val language = languageViewModel.getLanguageById(entry.languageCode)
            val ttsAvailable = TextToSpeechHelper.isPlayable(context, language)
            dictionaryViewModel.updateCurrentEntryData(entry, language, ttsAvailable)
        }
    }

    // Developer Entry Update
    LaunchedEffect(developerEntry) {
        developerEntry?.let { devEntry ->
            val language = languageViewModel.getLanguageById(devEntry.languageCode)
            val ttsAvailable = TextToSpeechHelper.isPlayable(context, language)
            dictionaryViewModel.updateCurrentEntryData(devEntry, language, ttsAvailable)
        }
    }

    // Navigation Effect
    LaunchedEffect(entryToNavigate) {
        entryToNavigate?.let { targetEntry ->
            dictionaryViewModel.setInternalNavigation()
            @Suppress("HardCodedStringLiteral")
            navController.navigate("dictionary_result/${targetEntry.id}")
            dictionaryViewModel.onNavigationDone()
        }
    }

    // Load local entries using ViewModel's method
    LaunchedEffect(entryData) {
        entryData?.let { data ->
            val langCode = data.language?.code
            if (langCode != null) {
                dictionaryViewModel.loadLocalEntriesForEntry(data.entry, langCode)
            } else {
                dictionaryViewModel.clearLocalEntries()
            }
        } ?: run {
            dictionaryViewModel.clearLocalEntries()
        }
    }

    DisposableEffect(entryId) {
        onDispose {
            dictionaryViewModel.clearCurrentEntryId()
            // Only clear breadcrumbs if this is truly leaving the screen
            // (not just internal navigation to a new entry)
            dictionaryViewModel.onLeavingDictionaryResultScreen()
        }
    }

    val isGenerating = entryData?.entry?.id?.let { generatingEntryIds.contains(it) } == true

    // Prepare FAB Items
    val fabItems = remember(entryData, isGenerating, isTtsAvailable, isDeveloperModeEnabled) {
        createFabItems(
            entryData = entryData,
            isGenerating = isGenerating,
            isTtsAvailable = isTtsAvailable,
            isDeveloperModeEnabled = isDeveloperModeEnabled,
            onCycleDev = { lang -> dictionaryViewModel.developerCycleLocalDictionaryEntries(lang) },
            onRegenerate = { data ->
                scope.launch {
                    dictionaryViewModel.performSearch(data.entry.word, data.language!!, regenerate = true)
                }
            },
            onAddToVocab = { showAddVocabularyDialog = true },
            onReadAloud = { data ->
                scope.launch {
                    val voice = settingsViewModel.getTtsVoiceForLanguage(data.language!!.code, data.language.region)
                    TextToSpeechHelper.speakOut(context, data.entry.word, data.language, voice)
                }
            },
            context = context
        )
    }

    DictionaryResultContent(
        entryData = entryData,
        localEntries = localEntries,
        breadcrumbs = breadcrumbs.map { BreadcrumbItem(it.word, it.id) },
        isGenerating = isGenerating,
        isDeveloperModeEnabled = isDeveloperModeEnabled,
        fabItems = fabItems,
        navController = navController,
        dictionaryViewModel = dictionaryViewModel,
        allLanguages = allLanguages,
        onNavigateBack = { navController.popBackStack() }
    )

    if (showAddVocabularyDialog) {
        entryData?.let {
            AddVocabularyDialog(
                initialWord = it.entry.word,
                onDismissRequest = {
                    @Suppress("AssignedValueIsNeverRead")
                    showAddVocabularyDialog = false
                }
            )
        }
    }
}

// Extracted Helper for FAB creation
private fun createFabItems(
    entryData: DictionaryViewModel.EntryData?,
    isGenerating: Boolean,
    isTtsAvailable: Boolean,
    isDeveloperModeEnabled: Boolean,
    onCycleDev: (Language) -> Unit,
    onRegenerate: (DictionaryViewModel.EntryData) -> Unit,
    onAddToVocab: () -> Unit,
    onReadAloud: (DictionaryViewModel.EntryData) -> Unit,
    context: Context,
): List<FabMenuItem> {
    if (entryData == null) return emptyList()
    val items = mutableListOf<FabMenuItem>()

    if (isDeveloperModeEnabled && entryData.language != null) {
        items.add(FabMenuItem(context.getString(R.string.label_auto_cycle_dev), AppIcons.Settings) { onCycleDev(entryData.language) })
    }

    if (!isGenerating) {
        items.add(FabMenuItem(context.getString(R.string.label_regenerate), AppIcons.Refresh) { onRegenerate(entryData) })
    }

    items.add(FabMenuItem(context.getString(R.string.label_add_to_dictionary), AppIcons.AddTo) { onAddToVocab() })

    if (isTtsAvailable) {
        items.add(FabMenuItem(context.getString(R.string.label_read_aloud), AppIcons.Speech) { onReadAloud(entryData) })
    }
    return items
}

@Composable
fun DictionaryResultContent(
    entryData: DictionaryViewModel.EntryData?,
    localEntries: List<DictionaryWordEntry>,
    breadcrumbs: List<BreadcrumbItem>,
    isGenerating: Boolean,
    isDeveloperModeEnabled: Boolean,
    fabItems: List<FabMenuItem>,
    navController: NavController,
    dictionaryViewModel: DictionaryViewModel,
    allLanguages: List<Language>,
    onNavigateBack: () -> Unit
) {
    val hasAiResult = entryData?.entry?.definition?.isNotEmpty() == true || isGenerating
    val hasLocalResult = localEntries.isNotEmpty()
    val showTabs = hasAiResult && hasLocalResult

    val aiTabTitle = stringResource(DictionaryResultTab.AI.titleRes)
    val localTabTitle = stringResource(DictionaryResultTab.Local.titleRes)

    val tabs = remember(aiTabTitle, localTabTitle) {
        listOf(
            DictionaryTabUi(DictionaryResultTab.AI, aiTabTitle, DictionaryResultTab.AI.icon),
            DictionaryTabUi(DictionaryResultTab.Local, localTabTitle, DictionaryResultTab.Local.icon)
        )
    }

    var selectedTab by remember { mutableStateOf(tabs.first()) }
    LaunchedEffect(showTabs) { if (!showTabs) selectedTab = tabs.first() }

    AppScaffold(
        topBar = {
            if (showTabs) {
                TabbedTopAppBar(
                    tabs = tabs,
                    selectedTab = selectedTab,
                    onTabSelected = { selectedTab = it },
                    onNavigateBack = onNavigateBack
                )
            } else {
                DictionarySimpleTopBar(
                    word = entryData?.entry?.word,
                    languageName = entryData?.language?.name,
                    onNavigateBack = onNavigateBack
                )
            }
        },
        floatingActionButton = {
            if (fabItems.isNotEmpty()) {
                AppFabMenu(items = fabItems)
            }
        }
    ) { paddingValues ->
        entryData?.let { data ->
            Column(
                modifier = Modifier
                    .fillMaxSize()
                    .padding(paddingValues)
            ) {
                val showAi = !showTabs || selectedTab.type == DictionaryResultTab.AI
                val showLocal = (!showTabs && hasLocalResult) || (showTabs && selectedTab.type == DictionaryResultTab.Local)

                if (showLocal) {
                    DictionaryResultBreadcrumbs(
                        breadcrumbs = breadcrumbs,
                        navController = navController
                    )
                }

                DefinitionBody(
                    modifier = Modifier
                        .fillMaxSize()
                        .padding(horizontal = 20.dp)
                        .verticalScroll(rememberScrollState()),
                    entry = data.entry,
                    localEntries = localEntries,
                    dictionaryViewModel = dictionaryViewModel,
                    allLanguages = allLanguages,
                    isGenerating = isGenerating,
                    isDeveloperModeEnabled = isDeveloperModeEnabled,
                    showAiContent = showAi,
                    showLocalContent = showLocal
                )
            }
        }
    }
}

@Composable
fun DictionarySimpleTopBar(
    word: String?,
    languageName: String?,
    onNavigateBack: () -> Unit
) {
    AppTopAppBar(
        title = "TODO",
        onNavigateBack =  onNavigateBack
    )
}

@Composable
fun DefinitionBody(
    modifier: Modifier = Modifier,
    entry: DictionaryEntry,
    localEntries: List<DictionaryWordEntry>,
    dictionaryViewModel: DictionaryViewModel,
    allLanguages: List<Language>,
    isGenerating: Boolean,
    isDeveloperModeEnabled: Boolean,
    showAiContent: Boolean = true,
    showLocalContent: Boolean = true
) {
    Column(
        modifier = modifier,
        verticalArrangement = Arrangement.spacedBy(24.dp)
    ) {
        if (showAiContent) {
            AiDefinitionsSection(
                definitionParts = entry.definition,
                isGenerating = isGenerating,
                hasOtherContent = showLocalContent
            )
        }

        if (showLocalContent) {
            DictionaryResultLocalEntriesSection(
                localEntries = localEntries,
                dictionaryViewModel = dictionaryViewModel,
                allLanguages = allLanguages,
                isDeveloperModeEnabled = isDeveloperModeEnabled
            )
        }

        if (isGenerating && entry.definition.isNotEmpty() && showAiContent) {
            GeneratingAnimation()
        }

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

@Composable
private fun AiDefinitionsSection(
    definitionParts: List<eu.gaudian.translator.model.EntryPart>,
    isGenerating: Boolean,
    hasOtherContent: Boolean
) {
    if (definitionParts.isNotEmpty()) {
        definitionParts.forEach { part ->
            DefinitionPart(part = part)
        }
    } else if (isGenerating) {
        GeneratingAnimation()
    } else if (!hasOtherContent) {
        Text(
            text = stringResource(R.string.text_no_data_available),
            style = MaterialTheme.typography.bodyLarge,
            fontStyle = FontStyle.Italic,
            color = MaterialTheme.colorScheme.onSurfaceVariant
        )
    }
}
