package de.ypchat.android.ui

import android.Manifest
import android.content.Context
import android.content.pm.PackageManager
import android.graphics.Bitmap
import android.net.Uri
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.PickVisualMediaRequest
import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.Image
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
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.layout.width
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.LazyRow
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.Card
import androidx.compose.material3.CardDefaults
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.DropdownMenuItem
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.ExposedDropdownMenuAnchorType
import androidx.compose.material3.ExposedDropdownMenuBox
import androidx.compose.material3.ExposedDropdownMenuDefaults
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.NavigationBar
import androidx.compose.material3.NavigationBarItem
import androidx.compose.material3.NavigationBarItemDefaults
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.OutlinedTextFieldDefaults
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
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.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Brush
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalUriHandler
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.text.input.PasswordVisualTransformation
import androidx.compose.ui.unit.dp
import coil3.compose.AsyncImage
import de.ypchat.android.R
import de.ypchat.android.data.model.ChatMessageDto
import de.ypchat.android.data.model.CountryOption
import de.ypchat.android.data.model.FeedbackItemDto
import de.ypchat.android.data.model.PartnerLinkDto
import de.ypchat.android.data.model.UserDto
import de.ypchat.android.data.repository.ChatState
import de.ypchat.android.data.repository.CommandTableState
import java.time.Instant
import java.time.ZoneId
import java.time.format.DateTimeFormatter
import java.time.format.FormatStyle
import java.io.File
import java.io.FileOutputStream

enum class AppTab(val labelRes: Int) {
    Online(R.string.tab_online),
    Search(R.string.tab_search),
    Inbox(R.string.tab_inbox),
    History(R.string.tab_history),
    Console(R.string.tab_console),
    More(R.string.tab_more)
}

private enum class MoreSection {
    Overview, Feedback, Partners, Faq, Rules, Safety, Privacy, Imprint
}

private val BgApp = Color(0xFFF4F6F5)
private val BgShell = Color(0xFFEDF2EE)
private val SurfaceColor = Color.White
private val SurfaceSubtle = Color(0xFFF6F9F7)
private val SurfaceSoftGreen = Color(0xFFF0F7F2)
private val SurfaceSoftBlue = Color(0xFFF1F5FA)
private val SurfaceSoftRed = Color(0xFFFBEDED)
private val BorderColor = Color(0xFFD7DFD9)
private val TextStrong = Color(0xFF18201B)
private val TextMuted = Color(0xFF637067)
private val Primary700 = Color(0xFF245C3A)
private val Primary600 = Color(0xFF2F6F46)
private val Primary500 = Color(0xFF3D8654)
private val Primary100 = Color(0xFFE7F1EA)
private val Danger = Color(0xFFA24040)
private const val PrivacyPolicyUrl = "https://www.ypchat.net/datenschutz"

private data class GenderOption(val value: String, val label: String)
private data class SmileyItem(val token: String, val hexCode: String, val tooltip: String)
private val SmileyItems = listOf(
    SmileyItem(":)", "1F642", "Smile"),
    SmileyItem(":D", "1F600", "Laugh"),
    SmileyItem(":(", "1F641", "Sad"),
    SmileyItem(";)", "1F609", "Twinkle"),
    SmileyItem(":p", "1F60B", "Tongue"),
    SmileyItem(";p", "1F61C", "Twinkle tongue"),
    SmileyItem("O)", "1F607", "Angel"),
    SmileyItem(":*", "1F617", "Kiss"),
    SmileyItem("(h)", "1FA77", "Heart"),
    SmileyItem("xD", "1F602", "Laughing hard"),
    SmileyItem(":@", "1F635", "Confused"),
    SmileyItem(":O", "1F632", "Surprised"),
    SmileyItem(":3", "1F63A", "Cat face"),
    SmileyItem(":|", "1F610", "Neutral"),
    SmileyItem(":/", "1FAE4", "Skeptical"),
    SmileyItem(":#", "1F912", "Sick"),
    SmileyItem("#)", "1F973", "Partied"),
    SmileyItem("%)", "1F974", "Drunk"),
    SmileyItem("(t)", "1F44D", "Thumbs up"),
    SmileyItem(":'(", "1F622", "Cry")
)

@Composable
fun YpChatRoot(viewModel: ChatViewModel) {
    val state by viewModel.state.collectAsState()

    MaterialTheme {
        Surface(modifier = Modifier.fillMaxSize()) {
            if (!state.isLoggedIn) {
                LoginScreen(state, onLogin = viewModel::login)
            } else {
                ChatShell(state, viewModel)
            }
        }
    }
}

@Composable
private fun LoginScreen(state: ChatState, onLogin: (String, String, Int, String) -> Unit) {
    var name by remember { mutableStateOf("") }
    var gender by remember { mutableStateOf("") }
    var age by remember { mutableStateOf(18.toString()) }
    var country by remember { mutableStateOf("Germany") }
    val scrollState = rememberScrollState()

    LaunchedEffect(state.savedProfile) {
        name = state.savedProfile.nickname
        gender = state.savedProfile.gender
        age = state.savedProfile.age.toString()
        country = state.savedProfile.country
    }

    Box(
        modifier = Modifier
            .fillMaxSize()
            .background(Brush.verticalGradient(listOf(BgApp, BgShell)))
            .verticalScroll(scrollState)
            .padding(16.dp),
        contentAlignment = Alignment.TopCenter
    ) {
        Column(modifier = Modifier.fillMaxWidth(), verticalArrangement = Arrangement.spacedBy(16.dp)) {
            LandingIntroCard()
            Card(
                modifier = Modifier.fillMaxWidth(),
                shape = RoundedCornerShape(20.dp),
                colors = CardDefaults.cardColors(containerColor = SurfaceColor.copy(alpha = 0.99f)),
                border = androidx.compose.foundation.BorderStroke(1.dp, Color(0xFFD4DDD6))
            ) {
                Column(modifier = Modifier.padding(24.dp), verticalArrangement = Arrangement.spacedBy(14.dp)) {
                    Text(
                        stringResource(R.string.profile_title),
                        style = MaterialTheme.typography.headlineSmall,
                        fontWeight = FontWeight.Bold,
                        color = TextStrong
                    )
                    Text(stringResource(R.string.profile_copy), color = TextMuted)
                    AppTextField(name, { name = it }, stringResource(R.string.label_nick))
                    GenderDropdown(value = gender, onValueChange = { gender = it })
                    OutlinedTextField(
                        value = age,
                        onValueChange = { age = it.filter(Char::isDigit) },
                        label = { Text(stringResource(R.string.label_age)) },
                        keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number),
                        modifier = Modifier.fillMaxWidth(),
                        colors = appTextFieldColors()
                    )
                    CountryDropdown(value = country, countries = state.countries, onValueChange = { country = it })
                    Button(
                        onClick = { onLogin(name, gender, age.toIntOrNull() ?: 18, country) },
                        enabled = name.length >= 3 && gender.isNotBlank() && country.isNotBlank(),
                        modifier = Modifier.fillMaxWidth(),
                        colors = ButtonDefaults.buttonColors(containerColor = Primary600, contentColor = Color.White)
                    ) {
                        Text(stringResource(R.string.button_start_chat))
                    }
                    state.errorMessage?.let { Text(localizeRuntimeMessage(it), color = Danger) }
                    Text(
                        text = if (state.isConnected) stringResource(R.string.socket_connected) else stringResource(R.string.socket_connecting),
                        color = TextMuted
                    )
                }
            }
        }
    }
}

@Composable
private fun LandingIntroCard() {
    Card(
        modifier = Modifier.fillMaxWidth(),
        shape = RoundedCornerShape(20.dp),
        colors = CardDefaults.cardColors(containerColor = Color(0xFFF4F8F5).copy(alpha = 0.98f)),
        border = androidx.compose.foundation.BorderStroke(1.dp, Color(0xFFCFE0D3))
    ) {
        Column(
            modifier = Modifier
                .background(Brush.radialGradient(colors = listOf(Color(0x473D8654), Color.Transparent), radius = 520f))
                .padding(24.dp),
            verticalArrangement = Arrangement.spacedBy(12.dp)
        ) {
            Text(
                text = stringResource(R.string.landing_eyebrow),
                color = Color(0xFF496254),
                style = MaterialTheme.typography.labelMedium,
                fontWeight = FontWeight.Bold
            )
            Text(
                text = stringResource(R.string.landing_title),
                color = TextStrong,
                style = MaterialTheme.typography.headlineMedium,
                fontWeight = FontWeight.Black
            )
            Text(text = stringResource(R.string.landing_copy), color = Color(0xFF4F5D54), style = MaterialTheme.typography.bodyMedium)
            Row(horizontalArrangement = Arrangement.spacedBy(8.dp)) {
                FeatureChip(stringResource(R.string.feature_worldwide_chat))
                FeatureChip(stringResource(R.string.feature_image_exchange))
            }
            FeatureChip(stringResource(R.string.feature_compact_controls))
        }
    }
}

@Composable
private fun FeatureChip(text: String) {
    Text(
        text = text,
        modifier = Modifier
            .background(Color(0xFFE2EFE5), RoundedCornerShape(999.dp))
            .padding(horizontal = 12.dp, vertical = 7.dp),
        color = Primary700,
        style = MaterialTheme.typography.labelMedium,
        fontWeight = FontWeight.Bold
    )
}

@Composable
private fun ChatShell(state: ChatState, viewModel: ChatViewModel) {
    var selectedTab by rememberSaveable { mutableStateOf(AppTab.Online) }
    var moreSection by rememberSaveable { mutableStateOf(MoreSection.Overview) }

    LaunchedEffect(selectedTab) {
        when (selectedTab) {
            AppTab.Inbox -> viewModel.requestInbox()
            AppTab.History -> viewModel.requestHistory()
            AppTab.More -> {
                viewModel.loadFeedback()
                viewModel.loadFeedbackAdminStatus()
                viewModel.loadPartners()
            }
            else -> Unit
        }
    }

    Scaffold(
        topBar = { TopStatusBar(state, onLogout = viewModel::logout) },
        bottomBar = {
            if (state.currentConversation == null) {
                NavigationBar {
                    AppTab.entries.forEach { tab ->
                        val baseLabel = stringResource(tab.labelRes)
                        val label = if (tab == AppTab.Inbox && state.unreadChatsCount > 0) "$baseLabel (${state.unreadChatsCount})" else baseLabel
                        NavigationBarItem(
                            selected = selectedTab == tab,
                            onClick = {
                                selectedTab = tab
                                if (tab != AppTab.More) moreSection = MoreSection.Overview
                            },
                            icon = {},
                            label = { Text(label) },
                            colors = NavigationBarItemDefaults.colors(
                                selectedIconColor = Primary700,
                                selectedTextColor = Primary700,
                                indicatorColor = Primary100,
                                unselectedTextColor = TextMuted
                            )
                        )
                    }
                }
            }
        }
    ) { padding ->
        Box(modifier = Modifier.padding(padding).fillMaxSize()) {
            if (state.currentConversation != null) {
                ChatScreen(state, viewModel)
            } else {
                when (selectedTab) {
                    AppTab.Online -> UserListScreen(state.users, state.countries, onUserClick = viewModel::openConversation)
                    AppTab.Search -> SearchScreen(state, viewModel)
                    AppTab.Inbox -> InboxScreen(state, viewModel)
                    AppTab.History -> HistoryScreen(state, viewModel)
                    AppTab.Console -> ConsoleScreen(state, viewModel)
                    AppTab.More -> MoreScreen(state, viewModel, moreSection) { moreSection = it }
                }
            }
        }
    }
}

@Composable
private fun TopStatusBar(state: ChatState, onLogout: () -> Unit) {
    Row(
        modifier = Modifier
            .fillMaxWidth()
            .background(Brush.verticalGradient(listOf(Color(0xFFD0E8D8), Color(0xFFEBF5EE), Color(0xFFF7FAF8))))
            .padding(16.dp),
        verticalAlignment = Alignment.CenterVertically
    ) {
        Column(modifier = Modifier.weight(1f)) {
            Text(stringResource(R.string.app_name), color = Primary700, fontWeight = FontWeight.Bold)
            Text(
                "${state.currentUser?.userName.orEmpty()} - ${if (state.isConnected) stringResource(R.string.status_online) else stringResource(R.string.status_connecting)}",
                color = TextMuted
            )
            Text(stringResource(R.string.timeout_in, formatTimeout(state.remainingSecondsToTimeout)), color = TextMuted)
        }
        TextButton(onClick = onLogout) { Text(stringResource(R.string.logout), color = Primary700) }
    }
}

@Composable
private fun UserListScreen(users: List<UserDto>, countries: List<CountryOption>, onUserClick: (String) -> Unit) {
    LazyColumn(modifier = Modifier.fillMaxSize().padding(16.dp), verticalArrangement = Arrangement.spacedBy(10.dp)) {
        item { Text(stringResource(R.string.tab_online), style = MaterialTheme.typography.headlineMedium, fontWeight = FontWeight.Bold) }
        if (users.isEmpty()) item { Text(stringResource(R.string.no_users_online)) }
        items(users) { user -> UserRow(user, countries, onUserClick) }
    }
}

@Composable
private fun UserRow(user: UserDto, countries: List<CountryOption>, onUserClick: (String) -> Unit) {
    val countryLabel = remember(user.country, user.isoCountryCode, countries) { displayCountryName(user, countries) }
    Card(modifier = Modifier.fillMaxWidth().clickable { onUserClick(user.userName) }) {
        Row(modifier = Modifier.padding(16.dp), verticalAlignment = Alignment.CenterVertically) {
            Text(user.userName, fontWeight = FontWeight.Bold, modifier = Modifier.weight(1f))
            Text("${user.age} - $countryLabel", color = TextMuted)
        }
    }
}

@Composable
private fun SearchScreen(state: ChatState, viewModel: ChatViewModel) {
    var query by remember { mutableStateOf("") }
    var minAge by remember { mutableStateOf("") }
    var maxAge by remember { mutableStateOf("") }
    var country by remember { mutableStateOf("") }
    var gender by remember { mutableStateOf("") }
    var localError by remember { mutableStateOf<String?>(null) }
    var hasSearched by remember { mutableStateOf(false) }
    val minAgeError = stringResource(R.string.search_min_age_error)

    Column(modifier = Modifier.fillMaxSize().padding(16.dp), verticalArrangement = Arrangement.spacedBy(12.dp)) {
        Text(stringResource(R.string.tab_search), style = MaterialTheme.typography.headlineMedium, fontWeight = FontWeight.Bold)
        OutlinedTextField(query, { query = it }, label = { Text(stringResource(R.string.search_username_includes)) }, modifier = Modifier.fillMaxWidth(), colors = appTextFieldColors())
        Row(horizontalArrangement = Arrangement.spacedBy(8.dp)) {
            OutlinedTextField(
                value = minAge,
                onValueChange = { minAge = it.filter(Char::isDigit) },
                label = { Text(stringResource(R.string.search_from_age)) },
                keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number),
                modifier = Modifier.weight(1f),
                colors = appTextFieldColors()
            )
            OutlinedTextField(
                value = maxAge,
                onValueChange = { maxAge = it.filter(Char::isDigit) },
                label = { Text(stringResource(R.string.search_to_age)) },
                keyboardOptions = KeyboardOptions(keyboardType = KeyboardType.Number),
                modifier = Modifier.weight(1f),
                colors = appTextFieldColors()
            )
        }
        CountryDropdown(value = country, countries = state.countries, allLabel = stringResource(R.string.search_all), onValueChange = { country = it })
        GenderDropdown(value = gender, allLabel = stringResource(R.string.search_all), onValueChange = { gender = it })
        localError?.let { Text(it, color = Danger) }
        Button(
            onClick = {
                val min = minAge.toIntOrNull()
                val max = maxAge.toIntOrNull()
                if (min != null && max != null && min > max) {
                    localError = minAgeError
                    return@Button
                }
                localError = null
                hasSearched = true
                viewModel.search(
                    name = query,
                    minAge = min,
                    maxAge = max,
                    countries = country.takeIf { it.isNotBlank() }?.let(::listOf).orEmpty(),
                    genders = gender.takeIf { it.isNotBlank() }?.let(::listOf).orEmpty()
                )
            },
            colors = ButtonDefaults.buttonColors(containerColor = Primary600),
            modifier = Modifier.fillMaxWidth()
        ) { Text(stringResource(R.string.search_button)) }
        if (hasSearched && state.searchResults.isEmpty()) {
            Text(stringResource(R.string.search_no_results), color = TextMuted)
        }
        LazyColumn(verticalArrangement = Arrangement.spacedBy(10.dp)) {
            items(state.searchResults) { user -> UserRow(user, state.countries, viewModel::openConversation) }
        }
    }
}

@Composable
private fun InboxScreen(state: ChatState, viewModel: ChatViewModel) {
    LazyColumn(modifier = Modifier.fillMaxSize().padding(16.dp), verticalArrangement = Arrangement.spacedBy(10.dp)) {
        item { Text(stringResource(R.string.tab_inbox), style = MaterialTheme.typography.headlineMedium, fontWeight = FontWeight.Bold) }
        if (state.inboxResults.isEmpty()) item { Text(stringResource(R.string.inbox_empty)) }
        items(state.inboxResults) { item ->
            Card(modifier = Modifier.fillMaxWidth().clickable { viewModel.openConversation(item.userName) }) {
                Row(modifier = Modifier.padding(16.dp)) {
                    Text(item.userName, fontWeight = FontWeight.Bold, modifier = Modifier.weight(1f))
                    Text(stringResource(R.string.inbox_new_count, item.unreadCount))
                }
            }
        }
    }
}

@Composable
private fun HistoryScreen(state: ChatState, viewModel: ChatViewModel) {
    LazyColumn(modifier = Modifier.fillMaxSize().padding(16.dp), verticalArrangement = Arrangement.spacedBy(10.dp)) {
        item { Text(stringResource(R.string.tab_history), style = MaterialTheme.typography.headlineMedium, fontWeight = FontWeight.Bold) }
        if (state.historyResults.isEmpty()) item { Text(stringResource(R.string.history_empty)) }
        items(state.historyResults) { item ->
            Card(modifier = Modifier.fillMaxWidth().clickable { viewModel.openConversation(item.userName) }) {
                Column(modifier = Modifier.padding(16.dp)) {
                    Text(item.userName, fontWeight = FontWeight.Bold)
                    Text(item.lastMessage?.message ?: stringResource(R.string.no_message), color = TextMuted)
                }
            }
        }
    }
}

@Composable
private fun ConsoleScreen(state: ChatState, viewModel: ChatViewModel) {
    var input by remember { mutableStateOf("") }
    val placeholder = when {
        state.awaitingLoginUsername -> stringResource(R.string.feedback_admin_user)
        state.awaitingLoginPassword -> stringResource(R.string.feedback_admin_password)
        else -> stringResource(R.string.console_placeholder)
    }

    Column(modifier = Modifier.fillMaxSize().padding(16.dp), verticalArrangement = Arrangement.spacedBy(12.dp)) {
        Text(stringResource(R.string.console_title), style = MaterialTheme.typography.headlineMedium, fontWeight = FontWeight.Bold)
        OutlinedTextField(
            value = input,
            onValueChange = { input = it },
            modifier = Modifier.fillMaxWidth(),
            label = { Text(placeholder) },
            colors = appTextFieldColors()
        )
        Button(
            onClick = {
                viewModel.sendMessage(input)
                input = ""
            },
            enabled = input.isNotBlank(),
            colors = ButtonDefaults.buttonColors(containerColor = Primary600),
            modifier = Modifier.fillMaxWidth()
        ) { Text(stringResource(R.string.console_send)) }

        if (state.commandLines.isEmpty() && state.commandTable == null) {
            Text(stringResource(R.string.console_empty), color = TextMuted)
        } else {
            state.commandLines.forEach { line ->
                ConsoleLineCard(line = localizeRuntimeMessage(line), kind = state.commandKind)
            }
            state.commandTable?.let { table -> CommandTableCard(table) }
        }
    }
}

@Composable
private fun CommandTableCard(table: CommandTableState) {
    Card(
        modifier = Modifier.fillMaxWidth(),
        colors = CardDefaults.cardColors(containerColor = SurfaceColor),
        border = androidx.compose.foundation.BorderStroke(1.dp, BorderColor)
    ) {
        Column(modifier = Modifier.padding(16.dp), verticalArrangement = Arrangement.spacedBy(10.dp)) {
            Text(table.title, fontWeight = FontWeight.Bold, color = TextStrong)
            if (table.columns.isNotEmpty()) {
                Row(
                    modifier = Modifier
                        .fillMaxWidth()
                        .background(Primary100, RoundedCornerShape(12.dp))
                        .padding(horizontal = 10.dp, vertical = 8.dp),
                    horizontalArrangement = Arrangement.spacedBy(10.dp)
                ) {
                    table.columns.forEach { Text(it, fontWeight = FontWeight.Bold, color = Primary700, modifier = Modifier.weight(1f, fill = false)) }
                }
            }
            table.rows.forEach { row ->
                Row(
                    modifier = Modifier
                        .fillMaxWidth()
                        .background(SurfaceSubtle, RoundedCornerShape(12.dp))
                        .padding(horizontal = 10.dp, vertical = 8.dp),
                    horizontalArrangement = Arrangement.spacedBy(10.dp)
                ) {
                    row.forEach { value -> Text(value, color = TextMuted, modifier = Modifier.weight(1f, fill = false)) }
                }
            }
        }
    }
}

@Composable
private fun ConsoleLineCard(line: String, kind: String?) {
    val normalizedKind = kind.orEmpty()
    val container = when {
        normalizedKind.startsWith("login") -> SurfaceSoftBlue
        normalizedKind == "info" -> SurfaceSoftGreen
        normalizedKind == "error" -> SurfaceSoftRed
        else -> SurfaceSubtle
    }
    val border = when {
        normalizedKind.startsWith("login") -> Color(0xFFC9DBEE)
        normalizedKind == "info" -> Color(0xFFCEE3D3)
        normalizedKind == "error" -> Color(0xFFF0CACA)
        else -> BorderColor
    }
    val textColor = if (normalizedKind == "error") Danger else TextStrong

    Card(
        modifier = Modifier.fillMaxWidth(),
        colors = CardDefaults.cardColors(containerColor = container),
        border = androidx.compose.foundation.BorderStroke(1.dp, border)
    ) {
        Text(line, modifier = Modifier.padding(14.dp), color = textColor)
    }
}

@Composable
private fun MoreScreen(state: ChatState, viewModel: ChatViewModel, section: MoreSection, onSectionChange: (MoreSection) -> Unit) {
    when (section) {
        MoreSection.Overview -> MoreOverviewScreen(onSectionChange)
        MoreSection.Feedback -> FeedbackScreen(state, viewModel) { onSectionChange(MoreSection.Overview) }
        MoreSection.Partners -> PartnersScreen(state.partnerLinks, state.partnersError) { onSectionChange(MoreSection.Overview) }
        MoreSection.Faq -> StaticContentScreen(stringResource(R.string.faq_title), stringResource(R.string.faq_body)) { onSectionChange(MoreSection.Overview) }
        MoreSection.Rules -> StaticContentScreen(stringResource(R.string.rules_title), stringResource(R.string.rules_body)) { onSectionChange(MoreSection.Overview) }
        MoreSection.Safety -> StaticContentScreen(stringResource(R.string.safety_title), stringResource(R.string.safety_body)) { onSectionChange(MoreSection.Overview) }
        MoreSection.Privacy -> PrivacyScreen { onSectionChange(MoreSection.Overview) }
        MoreSection.Imprint -> StaticContentScreen(stringResource(R.string.imprint_title), stringResource(R.string.imprint_body)) { onSectionChange(MoreSection.Overview) }
    }
}

@Composable
private fun MoreOverviewScreen(onSectionChange: (MoreSection) -> Unit) {
    LazyColumn(modifier = Modifier.fillMaxSize().padding(16.dp), verticalArrangement = Arrangement.spacedBy(12.dp)) {
        item { Text(stringResource(R.string.more_title), style = MaterialTheme.typography.headlineMedium, fontWeight = FontWeight.Bold) }
        item { MoreLinkCard(stringResource(R.string.more_feedback), stringResource(R.string.feedback_comment)) { onSectionChange(MoreSection.Feedback) } }
        item { MoreLinkCard(stringResource(R.string.more_partners), stringResource(R.string.partners_intro)) { onSectionChange(MoreSection.Partners) } }
        item { MoreLinkCard(stringResource(R.string.more_faq), stringResource(R.string.faq_intro)) { onSectionChange(MoreSection.Faq) } }
        item { MoreLinkCard(stringResource(R.string.more_rules), stringResource(R.string.rules_intro)) { onSectionChange(MoreSection.Rules) } }
        item { MoreLinkCard(stringResource(R.string.more_safety), stringResource(R.string.safety_intro)) { onSectionChange(MoreSection.Safety) } }
        item { MoreLinkCard(stringResource(R.string.more_privacy), stringResource(R.string.privacy_intro)) { onSectionChange(MoreSection.Privacy) } }
        item { MoreLinkCard(stringResource(R.string.more_imprint), stringResource(R.string.imprint_intro)) { onSectionChange(MoreSection.Imprint) } }
    }
}

@Composable
private fun MoreLinkCard(title: String, subtitle: String, onClick: () -> Unit) {
    Card(modifier = Modifier.fillMaxWidth().clickable(onClick = onClick)) {
        Column(modifier = Modifier.padding(16.dp), verticalArrangement = Arrangement.spacedBy(6.dp)) {
            Text(title, fontWeight = FontWeight.Bold, color = TextStrong)
            Text(subtitle, color = TextMuted)
        }
    }
}

@Composable
private fun FeedbackScreen(state: ChatState, viewModel: ChatViewModel, onBack: () -> Unit) {
    var comment by remember { mutableStateOf("") }
    var adminUser by remember { mutableStateOf("") }
    var adminPassword by remember { mutableStateOf("") }

    Column(modifier = Modifier.fillMaxSize().padding(16.dp), verticalArrangement = Arrangement.spacedBy(12.dp)) {
        BackHeader(stringResource(R.string.feedback_title), onBack)

        OutlinedTextField(
            value = comment,
            onValueChange = { comment = it },
            label = { Text(stringResource(R.string.feedback_comment)) },
            modifier = Modifier.fillMaxWidth(),
            minLines = 4,
            colors = appTextFieldColors()
        )
        Button(
            onClick = {
                viewModel.submitFeedback(comment)
                comment = ""
            },
            enabled = comment.isNotBlank(),
            colors = ButtonDefaults.buttonColors(containerColor = Primary600),
            modifier = Modifier.fillMaxWidth()
        ) { Text(stringResource(R.string.feedback_send)) }
        state.feedbackMessage?.let { Text(localizeRuntimeMessage(it), color = TextMuted) }

        Card(modifier = Modifier.fillMaxWidth(), colors = CardDefaults.cardColors(containerColor = SurfaceSubtle)) {
            Column(modifier = Modifier.padding(16.dp), verticalArrangement = Arrangement.spacedBy(8.dp)) {
                if (state.feedbackAdminAuthenticated) {
                    Text("${stringResource(R.string.feedback_admin_user)}: ${state.feedbackAdminUserName.orEmpty()}", fontWeight = FontWeight.Bold)
                    Button(
                        onClick = viewModel::logoutFeedbackAdmin,
                        colors = ButtonDefaults.buttonColors(containerColor = Primary500)
                    ) { Text(stringResource(R.string.feedback_admin_logout)) }
                } else {
                    OutlinedTextField(
                        value = adminUser,
                        onValueChange = { adminUser = it },
                        label = { Text(stringResource(R.string.feedback_admin_user)) },
                        modifier = Modifier.fillMaxWidth(),
                        colors = appTextFieldColors()
                    )
                    OutlinedTextField(
                        value = adminPassword,
                        onValueChange = { adminPassword = it },
                        label = { Text(stringResource(R.string.feedback_admin_password)) },
                        modifier = Modifier.fillMaxWidth(),
                        visualTransformation = PasswordVisualTransformation(),
                        colors = appTextFieldColors()
                    )
                    Button(
                        onClick = { viewModel.loginFeedbackAdmin(adminUser, adminPassword) },
                        colors = ButtonDefaults.buttonColors(containerColor = Primary500),
                        modifier = Modifier.fillMaxWidth()
                    ) { Text(stringResource(R.string.feedback_admin_login)) }
                }
                state.feedbackAdminError?.let { Text(localizeRuntimeMessage(it), color = Danger) }
            }
        }

        LazyColumn(verticalArrangement = Arrangement.spacedBy(10.dp)) {
            if (state.feedbackItems.isEmpty()) item { Text(stringResource(R.string.feedback_empty), color = TextMuted) }
            items(state.feedbackItems) { item -> FeedbackRow(item, state.feedbackAdminAuthenticated, viewModel) }
        }
    }
}

@Composable
private fun FeedbackRow(item: FeedbackItemDto, adminMode: Boolean, viewModel: ChatViewModel) {
    val metaSeparator = stringResource(R.string.feedback_meta_separator)
    val createdAtLabel = remember(item.createdAt) { formatFeedbackTimestamp(item.createdAt) }
    Card(modifier = Modifier.fillMaxWidth()) {
        Column(modifier = Modifier.padding(16.dp), verticalArrangement = Arrangement.spacedBy(6.dp)) {
            Row(verticalAlignment = Alignment.CenterVertically) {
                Text(item.name?.takeIf { it.isNotBlank() } ?: stringResource(R.string.anonymous), fontWeight = FontWeight.Bold, modifier = Modifier.weight(1f))
                if (adminMode) {
                    TextButton(onClick = { viewModel.deleteFeedback(item.id) }) { Text(stringResource(R.string.feedback_delete), color = Danger) }
                }
            }
            Text(item.comment, color = TextStrong)
            val meta = listOfNotNull(item.country, item.age?.toString(), item.gender).filter { it.isNotBlank() }
            if (meta.isNotEmpty()) Text(meta.joinToString(metaSeparator), color = TextMuted)
            createdAtLabel?.let {
                Text(stringResource(R.string.feedback_created_at, it), color = TextMuted, style = MaterialTheme.typography.bodySmall)
            }
        }
    }
}

@Composable
private fun PartnersScreen(links: List<PartnerLinkDto>, error: String?, onBack: () -> Unit) {
    val uriHandler = LocalUriHandler.current

    LazyColumn(modifier = Modifier.fillMaxSize().padding(16.dp), verticalArrangement = Arrangement.spacedBy(12.dp)) {
        item { BackHeader(stringResource(R.string.partners_title), onBack) }
        item { Text(stringResource(R.string.partners_intro), color = TextMuted) }
        error?.let { item { Text(localizeRuntimeMessage(it), color = Danger) } }
        items(links) { link ->
            Card(modifier = Modifier.fillMaxWidth().clickable { uriHandler.openUri(link.url) }) {
                Column(modifier = Modifier.padding(16.dp), verticalArrangement = Arrangement.spacedBy(4.dp)) {
                    Text(link.pageName, fontWeight = FontWeight.Bold, color = TextStrong)
                    Text(link.url, color = Primary700)
                    Text(stringResource(R.string.external_link), color = TextMuted)
                }
            }
        }
    }
}

@Composable
private fun PrivacyScreen(onBack: () -> Unit) {
    val uriHandler = LocalUriHandler.current

    Column(
        modifier = Modifier
            .fillMaxSize()
            .verticalScroll(rememberScrollState())
            .padding(16.dp),
        verticalArrangement = Arrangement.spacedBy(12.dp)
    ) {
        BackHeader(stringResource(R.string.privacy_title), onBack)
        Text(stringResource(R.string.privacy_body), color = TextStrong)
        Button(
            onClick = { uriHandler.openUri(PrivacyPolicyUrl) },
            colors = ButtonDefaults.buttonColors(containerColor = Primary600),
            modifier = Modifier.fillMaxWidth()
        ) {
            Text(stringResource(R.string.privacy_open_policy))
        }
    }
}

@Composable
private fun StaticContentScreen(title: String, body: String, onBack: () -> Unit) {
    Column(
        modifier = Modifier
            .fillMaxSize()
            .verticalScroll(rememberScrollState())
            .padding(16.dp),
        verticalArrangement = Arrangement.spacedBy(12.dp)
    ) {
        BackHeader(title, onBack)
        Text(body, color = TextStrong)
    }
}

@Composable
private fun BackHeader(title: String, onBack: () -> Unit) {
    Row(verticalAlignment = Alignment.CenterVertically) {
        TextButton(onClick = onBack) { Text(stringResource(R.string.more_back), color = Primary700) }
        Spacer(Modifier.width(8.dp))
        Text(title, style = MaterialTheme.typography.headlineMedium, fontWeight = FontWeight.Bold)
    }
}

@Composable
private fun ChatScreen(state: ChatState, viewModel: ChatViewModel) {
    var draft by remember { mutableStateOf("") }
    var showSmileys by remember { mutableStateOf(false) }
    val context = LocalContext.current
    val imagePicker = rememberLauncherForActivityResult(ActivityResultContracts.PickVisualMedia()) { uri ->
        if (uri != null) viewModel.sendImage(context, uri)
    }
    val cameraLauncher = rememberLauncherForActivityResult(ActivityResultContracts.TakePicturePreview()) { bitmap ->
        if (bitmap != null) {
            val uri = saveCameraBitmap(context, bitmap)
            if (uri != null) {
                viewModel.sendImage(context, uri)
            } else {
                viewModel.setImageUploadMessage("Camera capture failed")
            }
        } else {
            viewModel.setImageUploadMessage("Camera capture failed")
        }
    }
    val cameraPermissionLauncher = rememberLauncherForActivityResult(ActivityResultContracts.RequestPermission()) { granted ->
        if (granted) {
            cameraLauncher.launch(null)
        } else {
            viewModel.setImageUploadMessage("Camera permission denied")
        }
    }

    Column(modifier = Modifier.fillMaxSize()) {
        Row(modifier = Modifier.fillMaxWidth().padding(12.dp), verticalAlignment = Alignment.CenterVertically) {
            TextButton(onClick = viewModel::closeConversation) { Text(stringResource(R.string.back)) }
            Text(state.currentConversation.orEmpty(), fontWeight = FontWeight.Bold, modifier = Modifier.weight(1f))
            TextButton(onClick = viewModel::blockCurrentUser) { Text(stringResource(R.string.block)) }
            TextButton(onClick = viewModel::unblockCurrentUser) { Text(stringResource(R.string.unblock)) }
        }
        HorizontalDivider()
        LazyColumn(modifier = Modifier.weight(1f).padding(12.dp), verticalArrangement = Arrangement.spacedBy(8.dp)) {
            items(state.messages) { message -> MessageBubble(message, state.currentUser?.userName.orEmpty()) }
        }
        if (state.isUploadingImage || !state.imageUploadMessage.isNullOrBlank()) {
            UploadStatusBanner(state)
        }
        Row(modifier = Modifier.fillMaxWidth().padding(12.dp), verticalAlignment = Alignment.CenterVertically) {
            OutlinedTextField(
                draft,
                { draft = it },
                modifier = Modifier.weight(1f),
                placeholder = { Text(stringResource(R.string.message_placeholder)) },
                colors = appTextFieldColors(),
                enabled = !state.isUploadingImage
            )
            Spacer(Modifier.width(8.dp))
            IconImageButton(
                iconRes = R.drawable.smileys_button,
                contentDescription = stringResource(R.string.button_smileys),
                onClick = { showSmileys = !showSmileys },
                enabled = !state.isUploadingImage
            )
            Spacer(Modifier.width(8.dp))
            IconImageButton(
                iconRes = R.drawable.image_button,
                contentDescription = stringResource(R.string.button_image),
                onClick = { imagePicker.launch(PickVisualMediaRequest(ActivityResultContracts.PickVisualMedia.ImageOnly)) },
                enabled = !state.isUploadingImage
            )
            Spacer(Modifier.width(8.dp))
            TextButton(
                onClick = {
                    if (context.checkSelfPermission(Manifest.permission.CAMERA) == PackageManager.PERMISSION_GRANTED) {
                        cameraLauncher.launch(null)
                    } else {
                        cameraPermissionLauncher.launch(Manifest.permission.CAMERA)
                    }
                },
                enabled = !state.isUploadingImage,
                colors = ButtonDefaults.textButtonColors(
                    containerColor = Primary100,
                    contentColor = Primary700,
                    disabledContainerColor = SurfaceSubtle,
                    disabledContentColor = TextMuted
                )
            ) {
                Text(stringResource(R.string.button_camera), fontWeight = FontWeight.Bold)
            }
            Spacer(Modifier.width(8.dp))
            Button(
                onClick = { viewModel.sendMessage(draft); draft = "" },
                colors = ButtonDefaults.buttonColors(containerColor = Primary600),
                enabled = draft.isNotBlank() && !state.isUploadingImage
            ) {
                Text(stringResource(R.string.button_send))
            }
        }
        if (showSmileys) {
            LazyRow(modifier = Modifier.fillMaxWidth().padding(horizontal = 12.dp), horizontalArrangement = Arrangement.spacedBy(8.dp)) {
                items(SmileyItems) { smiley ->
                    Text(
                        text = smileyEmoji(smiley.hexCode),
                        modifier = Modifier
                            .background(Primary100, RoundedCornerShape(999.dp))
                            .clickable {
                                draft += smiley.token
                                showSmileys = false
                            }
                            .padding(horizontal = 12.dp, vertical = 8.dp),
                        color = Primary700,
                        fontWeight = FontWeight.Bold
                    )
                }
            }
        }
        state.errorMessage?.let { Text(localizeRuntimeMessage(it), modifier = Modifier.padding(horizontal = 12.dp), color = Danger) }
        Spacer(Modifier.height(8.dp))
    }
}

private fun saveCameraBitmap(context: Context, bitmap: Bitmap): Uri? {
    return runCatching {
        val file = File(context.cacheDir, "singlechat-photo-${System.currentTimeMillis()}.jpg")
        FileOutputStream(file).use { output ->
            bitmap.compress(Bitmap.CompressFormat.JPEG, 88, output)
        }
        Uri.fromFile(file)
    }.getOrNull()
}

@Composable
private fun UploadStatusBanner(state: ChatState) {
    val message = when {
        state.isUploadingImage -> stringResource(R.string.image_upload_in_progress)
        state.imageUploadMessage != null -> localizeRuntimeMessage(state.imageUploadMessage)
        else -> return
    }
    val backgroundColor = when {
        state.isUploadingImage -> SurfaceSoftBlue
        state.imageUploadMessage == "Image uploaded" -> SurfaceSoftGreen
        else -> SurfaceSoftRed
    }
    val textColor = when {
        state.isUploadingImage -> Primary700
        state.imageUploadMessage == "Image uploaded" -> Primary700
        else -> Danger
    }

    Card(
        modifier = Modifier
            .fillMaxWidth()
            .padding(horizontal = 12.dp),
        colors = CardDefaults.cardColors(containerColor = backgroundColor)
    ) {
        Text(
            text = message,
            modifier = Modifier.padding(horizontal = 14.dp, vertical = 10.dp),
            color = textColor,
            style = MaterialTheme.typography.bodyMedium
        )
    }
}

@Composable
private fun IconImageButton(iconRes: Int, contentDescription: String, onClick: () -> Unit, enabled: Boolean = true) {
    TextButton(
        onClick = onClick,
        enabled = enabled,
        colors = ButtonDefaults.textButtonColors(
            containerColor = Primary100,
            contentColor = Primary700,
            disabledContainerColor = SurfaceSubtle,
            disabledContentColor = TextMuted
        )
    ) {
        Image(
            painter = painterResource(iconRes),
            contentDescription = contentDescription,
            modifier = Modifier.height(20.dp)
        )
    }
}

@Composable
private fun MessageBubble(message: ChatMessageDto, currentUserName: String) {
    val self = message.from == currentUserName
    Row(modifier = Modifier.fillMaxWidth(), horizontalArrangement = if (self) Arrangement.End else Arrangement.Start) {
        Column(
            modifier = Modifier
                .background(if (self) Color(0xFFDFF0E4) else SurfaceSubtle, RoundedCornerShape(18.dp))
                .padding(12.dp)
        ) {
            if (message.isImage && !message.imageUrl.isNullOrBlank()) {
                AsyncImage(model = message.imageUrl, contentDescription = stringResource(R.string.image_message), modifier = Modifier.fillMaxWidth().height(220.dp))
            } else {
                Text(message.message)
            }
        }
    }
}

@Composable
private fun AppTextField(value: String, onValueChange: (String) -> Unit, label: String) {
    OutlinedTextField(
        value = value,
        onValueChange = onValueChange,
        label = { Text(label) },
        modifier = Modifier.fillMaxWidth(),
        colors = appTextFieldColors()
    )
}

@OptIn(ExperimentalMaterial3Api::class)
@Composable
private fun GenderDropdown(value: String, allLabel: String? = null, onValueChange: (String) -> Unit) {
    var expanded by remember { mutableStateOf(false) }
    val baseGenderOptions = listOf(
        GenderOption("F", stringResource(R.string.gender_female)),
        GenderOption("M", stringResource(R.string.gender_male)),
        GenderOption("P", stringResource(R.string.gender_pair)),
        GenderOption("TF", stringResource(R.string.gender_trans_mf)),
        GenderOption("TM", stringResource(R.string.gender_trans_fm))
    )
    val genderOptions = allLabel?.let { listOf(GenderOption("", it)) + baseGenderOptions } ?: baseGenderOptions
    val selectedLabel = genderOptions.firstOrNull { it.value == value }?.label.orEmpty()

    ExposedDropdownMenuBox(expanded = expanded, onExpandedChange = { expanded = it }) {
        OutlinedTextField(
            value = selectedLabel,
            onValueChange = {},
            readOnly = true,
            label = { Text(stringResource(R.string.label_gender)) },
            trailingIcon = { ExposedDropdownMenuDefaults.TrailingIcon(expanded = expanded) },
            modifier = Modifier.menuAnchor(ExposedDropdownMenuAnchorType.PrimaryNotEditable, true).fillMaxWidth(),
            colors = appTextFieldColors()
        )
        ExposedDropdownMenu(expanded = expanded, onDismissRequest = { expanded = false }) {
            genderOptions.forEach { option ->
                DropdownMenuItem(
                    text = { Text(option.label) },
                    onClick = {
                        onValueChange(option.value)
                        expanded = false
                    }
                )
            }
        }
    }
}

@OptIn(ExperimentalMaterial3Api::class)
@Composable
private fun CountryDropdown(value: String, countries: List<CountryOption>, allLabel: String? = null, onValueChange: (String) -> Unit) {
    var expanded by remember { mutableStateOf(false) }
    val visibleCountries = remember(countries) { if (countries.isEmpty()) listOf(CountryOption("Germany", "Germany", "de")) else countries }
    val selectedLabel = if (value.isBlank() && allLabel != null) allLabel else visibleCountries.firstOrNull { it.englishName == value }?.displayName ?: value

    ExposedDropdownMenuBox(expanded = expanded, onExpandedChange = { expanded = it }) {
        OutlinedTextField(
            value = selectedLabel,
            onValueChange = {},
            readOnly = true,
            label = { Text(stringResource(R.string.label_country)) },
            trailingIcon = { ExposedDropdownMenuDefaults.TrailingIcon(expanded = expanded) },
            modifier = Modifier.menuAnchor(ExposedDropdownMenuAnchorType.PrimaryNotEditable, true).fillMaxWidth(),
            colors = appTextFieldColors()
        )
        ExposedDropdownMenu(expanded = expanded, onDismissRequest = { expanded = false }) {
            allLabel?.let {
                DropdownMenuItem(
                    text = { Text(it) },
                    onClick = {
                        onValueChange("")
                        expanded = false
                    }
                )
            }
            visibleCountries.forEach { country ->
                DropdownMenuItem(
                    text = { Text(country.displayName) },
                    onClick = {
                        onValueChange(country.englishName)
                        expanded = false
                    }
                )
            }
        }
    }
}

private fun displayCountryName(user: UserDto, countries: List<CountryOption>): String {
    val byEnglishName = countries.firstOrNull { it.englishName == user.country }
    if (byEnglishName != null) return byEnglishName.displayName

    val byIsoCode = countries.firstOrNull { it.isoCode.equals(user.isoCountryCode, ignoreCase = true) }
    if (byIsoCode != null) return byIsoCode.displayName

    return user.country
}

@Composable
private fun appTextFieldColors() = OutlinedTextFieldDefaults.colors(
    focusedBorderColor = Primary500,
    unfocusedBorderColor = BorderColor,
    focusedLabelColor = Primary700,
    unfocusedLabelColor = TextMuted,
    cursorColor = Primary700,
    focusedContainerColor = SurfaceSubtle,
    unfocusedContainerColor = Color(0xFFFBFDFB)
)

@Composable
private fun localizeRuntimeMessage(message: String): String {
    return when {
        message.startsWith("Country list could not be loaded:") ->
            stringResource(R.string.countries_load_error, message.substringAfter(":").trim())
        message == "Image uploaded" ->
            stringResource(R.string.image_upload_success)
        message == "Image upload failed" ->
            stringResource(R.string.image_upload_failed)
        message == "Image exceeds 5 MB" ->
            stringResource(R.string.image_upload_too_large)
        message == "Image could not be opened" ->
            stringResource(R.string.image_upload_open_failed)
        message == "Camera permission denied" ->
            stringResource(R.string.camera_permission_denied)
        message == "Camera capture failed" ->
            stringResource(R.string.camera_capture_failed)
        message.endsWith(" blocked") ->
            stringResource(R.string.user_blocked, message.removeSuffix(" blocked"))
        message.endsWith(" unblocked") ->
            stringResource(R.string.user_unblocked, message.removeSuffix(" unblocked"))
        message == "Feedback saved" ->
            stringResource(R.string.feedback_saved)
        else -> message
    }
}

private fun formatTimeout(totalSeconds: Int): String {
    val minutes = totalSeconds / 60
    val seconds = totalSeconds % 60
    return "%d:%02d".format(minutes, seconds)
}

private fun smileyEmoji(hexCode: String): String {
    val codePoint = hexCode.toInt(16)
    return String(Character.toChars(codePoint))
}

private fun formatFeedbackTimestamp(createdAt: String): String? {
    if (createdAt.isBlank()) return null

    return runCatching {
        val formatter = DateTimeFormatter.ofLocalizedDateTime(FormatStyle.MEDIUM)
            .withZone(ZoneId.systemDefault())
        formatter.format(Instant.parse(createdAt))
    }.getOrNull()
}
