package dev.castarr.tv.ui

import android.graphics.Bitmap
import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.Canvas
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.border
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.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
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.draw.clip
import androidx.compose.ui.focus.FocusRequester
import androidx.compose.ui.focus.focusRequester
import androidx.compose.ui.graphics.Path
import androidx.compose.ui.graphics.asImageBitmap
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import androidx.compose.ui.window.Dialog
import androidx.compose.ui.window.DialogProperties
import androidx.tv.material3.Border
import androidx.tv.material3.ClickableSurfaceDefaults
import androidx.tv.material3.Surface
import androidx.tv.material3.Text
import dev.castarr.tv.AppState
import dev.castarr.tv.BuildConfig
import dev.castarr.tv.pairing.Pairing
import dev.castarr.tv.pairing.Qr
import dev.castarr.tv.update.UpdateChecker
import kotlinx.coroutines.launch

/** One open picker dialog: which setting, its options, what happens on pick. */
private data class Picker(
    val title: String,
    val options: List<String>,
    val selected: Int,
    val onPick: (Int) -> Unit,
)

/**
 * Google-TV-style settings: cards with full-width focusable rows; choices
 * open a picker dialog (Konto / Wiedergabe / App / Handy-Fernbedienung).
 * Ten-Foot-Regel (#14): no text fields, no scrolling.
 */
@Composable
fun SettingsScreen(state: AppState) {
    val context = LocalContext.current
    val scope = rememberCoroutineScope()
    val profiles by state.dispatcharr.profiles.collectAsState()
    var updateStatus by remember { mutableStateOf("") }
    var picker by remember { mutableStateOf<Picker?>(null) }
    // Bumped on reset so the QR code and the four-digit code redraw.
    var pairingEpoch by remember { mutableStateOf(0) }

    Row(
        Modifier
            .fillMaxSize()
            .padding(horizontal = 40.dp, vertical = 12.dp)
    ) {
        Column(Modifier.weight(1.25f), verticalArrangement = Arrangement.spacedBy(16.dp)) {
            SettingsCard("Konto") {
                if (state.auth.isLoggedIn) {
                    Row(
                        modifier = Modifier.padding(horizontal = 14.dp, vertical = 10.dp),
                        verticalAlignment = Alignment.CenterVertically,
                    ) {
                        Box(
                            Modifier
                                .size(34.dp)
                                .clip(CircleShape)
                                .background(CastarrColors.accentDim),
                            contentAlignment = Alignment.Center,
                        ) {
                            Text(
                                state.auth.username.take(1).uppercase().ifEmpty { "?" },
                                color = CastarrColors.accent,
                                fontFamily = AppFont,
                                fontSize = 15.sp,
                                fontWeight = FontWeight.SemiBold,
                            )
                        }
                        Spacer(Modifier.width(14.dp))
                        Column {
                            Text(
                                state.auth.username,
                                color = CastarrColors.fg, fontFamily = AppFont, fontSize = 15.sp,
                            )
                            Text(
                                "Angemeldet über SSO",
                                color = CastarrColors.faint, fontFamily = AppFont, fontSize = 11.sp,
                            )
                        }
                    }
                    SettingRow("Abmelden", danger = true) { state.startOnboarding() }
                } else {
                    Text(
                        "Nicht angemeldet.",
                        color = CastarrColors.muted, fontFamily = AppFont, fontSize = 14.sp,
                        modifier = Modifier.padding(horizontal = 14.dp, vertical = 6.dp),
                    )
                    SettingRow("Jetzt anmelden") { state.startOnboarding() }
                }
            }

            SettingsCard("Wiedergabe") {
                if (state.auth.isLoggedIn && state.source.m3uUrl.isNotEmpty()) {
                    val modes = listOf("Dispatcharr", "Eigene M3U")
                    val modeIndex = if (state.sourceMode == AppState.SourceMode.DISPATCHARR) 0 else 1
                    SettingRow(
                        "Quelle",
                        subtitle = "Woher die Senderliste kommt",
                        trailing = { ValueWithCaret(modes[modeIndex]) },
                    ) {
                        picker = Picker("Quelle", modes, modeIndex) { index ->
                            state.setMode(
                                if (index == 0) AppState.SourceMode.DISPATCHARR
                                else AppState.SourceMode.GENERIC
                            )
                        }
                    }
                }
                val qualities = listOf("Standard", "Original") + profiles
                val qualityIndex = when (state.outputProfile) {
                    "" -> 0
                    "raw" -> 1
                    else -> (profiles.indexOf(state.outputProfile) + 2).coerceAtLeast(0)
                }
                SettingRow(
                    "Stream-Qualität",
                    subtitle = "Standard remuxt nur den Ton",
                    trailing = { ValueWithCaret(qualities[qualityIndex]) },
                ) {
                    picker = Picker("Stream-Qualität", qualities, qualityIndex) { index ->
                        state.outputProfile = when (index) {
                            0 -> ""
                            1 -> "raw"
                            else -> profiles.getOrElse(index - 2) { "" }
                        }
                    }
                }
            }

            SettingsCard("Vereinsmenüs") {
                Text(
                    "Eigene Gruppe mit allen Sendern, auf denen der Verein in den " +
                        "nächsten 3 Stunden läuft. Bis zu " +
                        "${dev.castarr.tv.data.TeamFilters.MAX_ACTIVE} Vereine.",
                    color = CastarrColors.faint, fontFamily = AppFont, fontSize = 11.sp,
                    modifier = Modifier.padding(start = 14.dp, end = 14.dp, bottom = 6.dp),
                )
                val active = dev.castarr.tv.data.TeamFilters.all
                    .filter { it.key in state.enabledTeams }
                active.forEach { club ->
                    SettingRow(
                        club.fullName,
                        subtitle = "Erscheint als ${club.label} in der Senderliste",
                        trailing = { TogglePill(on = true) },
                    ) { state.toggleTeam(club.key) }
                }
                if (active.size < dev.castarr.tv.data.TeamFilters.MAX_ACTIVE) {
                    SettingRow(
                        "Verein hinzufügen",
                        subtitle = "1. bis 3. Liga",
                    ) {
                        val choices = dev.castarr.tv.data.TeamFilters.all
                            .filter { it.key !in state.enabledTeams }
                        picker = Picker(
                            "Verein hinzufügen",
                            choices.map { it.fullName },
                            -1,
                        ) { index ->
                            choices.getOrNull(index)?.let { state.toggleTeam(it.key) }
                        }
                    }
                }
            }

            SettingsCard("App") {
                SettingRow(
                    "Version ${BuildConfig.VERSION_NAME}",
                    subtitle = updateStatus.ifEmpty { "Klicken prüft auf Updates" },
                    trailing = state.updateAvailable?.let { version ->
                        {
                            Box(
                                Modifier
                                    .clip(RoundedCornerShape(999.dp))
                                    .background(CastarrColors.accentDim)
                                    .padding(horizontal = 10.dp, vertical = 4.dp)
                            ) {
                                Text(
                                    "$version verfügbar",
                                    color = CastarrColors.accent,
                                    fontFamily = AppFont,
                                    fontSize = 11.sp,
                                    fontWeight = FontWeight.SemiBold,
                                )
                            }
                        }
                    },
                ) {
                    scope.launch {
                        updateStatus = when (val v = UpdateChecker.check(state)) {
                            null -> "App ist aktuell"
                            else -> "$v verfügbar"
                        }
                    }
                }
                if (state.updateAvailable != null) {
                    SettingRow("Update installieren") {
                        scope.launch {
                            updateStatus = "Update wird heruntergeladen…"
                            updateStatus =
                                UpdateChecker.downloadAndInstall(context, state)
                                    ?: "Installation wird geöffnet…"
                        }
                    }
                }
                SettingRow(
                    "Erweitert",
                    subtitle = "M3U/EPG-Adressen von Hand eintragen",
                ) { state.screen = AppState.Screen.ADVANCED }
            }
        }

        Spacer(Modifier.width(16.dp))

        Column(Modifier.weight(0.75f)) {
            SettingsCard("Handy-Fernbedienung") {
                val address = remember(pairingEpoch) { Pairing.lanAddress() }
                if (!state.remoteAvailable) {
                    Text(
                        "Fernbedienung nicht verfügbar — Port belegt. Neustart des Fernsehers hilft meistens.",
                        color = CastarrColors.faint, fontFamily = AppFont, fontSize = 13.sp,
                        modifier = Modifier.padding(horizontal = 14.dp, vertical = 6.dp),
                    )
                } else if (address != null) {
                    val qr = remember(address, pairingEpoch) {
                        Qr.encode(
                            Pairing.pairingUrl(context, address), 400,
                            android.graphics.Color.parseColor("#101216"),
                        )
                    }
                    Column(
                        Modifier
                            .fillMaxWidth()
                            .padding(vertical = 6.dp),
                        horizontalAlignment = Alignment.CenterHorizontally,
                    ) {
                        QrCard(qr)
                        Spacer(Modifier.height(10.dp))
                        Text(
                            "Mit der Handy-Kamera scannen",
                            color = CastarrColors.faint, fontFamily = AppFont, fontSize = 12.sp,
                        )
                        Text(
                            "${Pairing.remoteUrl(address)}  ·  Code ${Pairing.code(context)}",
                            color = CastarrColors.muted, fontFamily = AppFont, fontSize = 12.sp,
                        )
                        Spacer(Modifier.height(10.dp))
                    }
                    SettingRow(
                        "Kopplung zurücksetzen",
                        subtitle = "Neuer Code, alle Handys müssen neu scannen",
                    ) {
                        Pairing.reset(context)
                        pairingEpoch++
                    }
                } else {
                    Text(
                        "Keine Netzwerkverbindung",
                        color = CastarrColors.faint, fontFamily = AppFont, fontSize = 13.sp,
                        modifier = Modifier.padding(horizontal = 14.dp, vertical = 6.dp),
                    )
                }
            }
        }
    }

    picker?.let { current ->
        PickerDialog(current) { picker = null }
    }
}

/** TV-friendly dropdown replacement: fullscreen scrim, options centered. */
@Composable
private fun PickerDialog(picker: Picker, onClose: () -> Unit) {
    val selectedFocus = remember { FocusRequester() }
    LaunchedEffect(Unit) { selectedFocus.requestFocus() }
    Dialog(
        onDismissRequest = onClose,
        properties = DialogProperties(usePlatformDefaultWidth = false),
    ) {
        Box(
            Modifier
                .fillMaxSize()
                // Own heavy scrim — the platform default is too light and
                // lets the white QR card fight the panel.
                .background(CastarrColors.bgDeep.copy(alpha = 0.88f)),
            contentAlignment = Alignment.Center,
        ) {
        Column(
            Modifier
                .width(360.dp)
                .clip(RoundedCornerShape(16.dp))
                .background(CastarrColors.surface)
                .padding(horizontal = 10.dp, vertical = 14.dp)
        ) {
            Text(
                picker.title.uppercase(),
                color = CastarrColors.faint,
                fontFamily = AppFont,
                fontSize = 11.sp,
                fontWeight = FontWeight.SemiBold,
                letterSpacing = 2.sp,
                modifier = Modifier.padding(start = 14.dp, bottom = 10.dp),
            )
            picker.options.forEachIndexed { index, option ->
                val selected = index == picker.selected
                Surface(
                    onClick = {
                        picker.onPick(index)
                        onClose()
                    },
                    modifier = Modifier
                        .fillMaxWidth()
                        .then(if (selected) Modifier.focusRequester(selectedFocus) else Modifier),
                    shape = ClickableSurfaceDefaults.shape(rowShape),
                    scale = ClickableSurfaceDefaults.scale(focusedScale = 1f),
                    colors = ClickableSurfaceDefaults.colors(
                        containerColor = androidx.compose.ui.graphics.Color.Transparent,
                        contentColor = CastarrColors.fg,
                        focusedContainerColor = CastarrColors.surfaceFocused,
                        focusedContentColor = CastarrColors.fg,
                    ),
                    border = ClickableSurfaceDefaults.border(
                        focusedBorder = Border(
                            border = BorderStroke(2.dp, CastarrColors.accent),
                            shape = rowShape,
                        ),
                    ),
                ) {
                    Row(
                        modifier = Modifier.padding(horizontal = 14.dp, vertical = 11.dp),
                        verticalAlignment = Alignment.CenterVertically,
                    ) {
                        Text(
                            option,
                            color = if (selected) CastarrColors.accent else CastarrColors.fg,
                            fontFamily = AppFont,
                            fontSize = 14.sp,
                            fontWeight = if (selected) FontWeight.SemiBold else FontWeight.Normal,
                            maxLines = 1,
                            overflow = TextOverflow.Ellipsis,
                            modifier = Modifier.weight(1f),
                        )
                        if (selected) {
                            Box(
                                Modifier
                                    .size(7.dp)
                                    .clip(CircleShape)
                                    .background(CastarrColors.accent)
                            )
                        }
                    }
                }
            }
        }
        }
    }
}

/** Current value plus a small drawn caret, shown at a row's trailing edge. */
@Composable
private fun ValueWithCaret(value: String) {
    Row(verticalAlignment = Alignment.CenterVertically) {
        Text(
            value,
            color = CastarrColors.muted,
            fontFamily = AppFont,
            fontSize = 13.sp,
            maxLines = 1,
            overflow = TextOverflow.Ellipsis,
        )
        Spacer(Modifier.width(8.dp))
        val color = CastarrColors.faint
        Canvas(Modifier.size(9.dp)) {
            drawPath(
                Path().apply {
                    moveTo(0f, size.height * 0.3f)
                    lineTo(size.width, size.height * 0.3f)
                    lineTo(size.width / 2f, size.height * 0.75f)
                    close()
                },
                color,
            )
        }
    }
}

@Composable
private fun TogglePill(on: Boolean) {
    Box(
        Modifier
            .clip(RoundedCornerShape(999.dp))
            .background(if (on) CastarrColors.accent else CastarrColors.bg)
            .padding(horizontal = 12.dp, vertical = 5.dp)
    ) {
        Text(
            if (on) "An" else "Aus",
            color = if (on) CastarrColors.onAccent else CastarrColors.muted,
            fontFamily = AppFont,
            fontSize = 12.sp,
            fontWeight = if (on) FontWeight.SemiBold else FontWeight.Normal,
        )
    }
}

@Composable
private fun SettingsCard(title: String, content: @Composable () -> Unit) {
    Column(
        Modifier
            .fillMaxWidth()
            .clip(RoundedCornerShape(16.dp))
            .background(CastarrColors.surface)
            .padding(horizontal = 10.dp, vertical = 14.dp)
    ) {
        Text(
            title.uppercase(),
            color = CastarrColors.faint,
            fontFamily = AppFont,
            fontSize = 11.sp,
            fontWeight = FontWeight.SemiBold,
            letterSpacing = 2.sp,
            modifier = Modifier.padding(start = 14.dp, bottom = 8.dp),
        )
        content()
    }
}

private val rowShape = RoundedCornerShape(10.dp)

/** One full-width focusable settings row: label + subtitle, value right. */
@Composable
private fun SettingRow(
    label: String,
    subtitle: String? = null,
    danger: Boolean = false,
    trailing: (@Composable () -> Unit)? = null,
    onClick: () -> Unit,
) {
    Surface(
        onClick = onClick,
        modifier = Modifier.fillMaxWidth(),
        shape = ClickableSurfaceDefaults.shape(rowShape),
        scale = ClickableSurfaceDefaults.scale(focusedScale = 1f),
        colors = ClickableSurfaceDefaults.colors(
            containerColor = androidx.compose.ui.graphics.Color.Transparent,
            contentColor = CastarrColors.fg,
            focusedContainerColor = CastarrColors.surfaceFocused,
            focusedContentColor = CastarrColors.fg,
        ),
        border = ClickableSurfaceDefaults.border(
            focusedBorder = Border(
                border = BorderStroke(2.dp, if (danger) CastarrColors.live else CastarrColors.accent),
                shape = rowShape,
            ),
        ),
    ) {
        Row(
            modifier = Modifier.padding(horizontal = 14.dp, vertical = 10.dp),
            verticalAlignment = Alignment.CenterVertically,
        ) {
            Column(Modifier.weight(1f)) {
                Text(
                    label,
                    color = if (danger) CastarrColors.live else CastarrColors.fg,
                    fontFamily = AppFont,
                    fontSize = 15.sp,
                    maxLines = 1,
                    overflow = TextOverflow.Ellipsis,
                )
                if (subtitle != null) {
                    Text(
                        subtitle,
                        color = CastarrColors.faint,
                        fontFamily = AppFont,
                        fontSize = 11.sp,
                        maxLines = 1,
                        overflow = TextOverflow.Ellipsis,
                    )
                }
            }
            if (trailing != null) {
                Spacer(Modifier.width(12.dp))
                trailing()
            }
        }
    }
}

@Composable
fun ActionButton(label: String, danger: Boolean = false, onClick: () -> Unit) {
    Surface(
        onClick = onClick,
        shape = ClickableSurfaceDefaults.shape(RoundedCornerShape(10.dp)),
        colors = ClickableSurfaceDefaults.colors(
            containerColor = if (danger) CastarrColors.surface else CastarrColors.accentDim,
            contentColor = if (danger) CastarrColors.muted else CastarrColors.accent,
            focusedContainerColor = if (danger) CastarrColors.live else CastarrColors.accent,
            focusedContentColor = if (danger) CastarrColors.fg else CastarrColors.onAccent,
        ),
    ) {
        Text(
            label,
            fontFamily = AppFont, fontSize = 13.sp,
            modifier = Modifier.padding(horizontal = 18.dp, vertical = 10.dp),
        )
    }
}

@Composable
fun QrCard(bitmap: Bitmap) {
    // Quiet zone stays white for scannability, but the tile sits in a
    // bordered frame on the card instead of floating as a bare white block.
    Column(
        Modifier
            .clip(RoundedCornerShape(18.dp))
            .background(CastarrColors.bg)
            .border(1.dp, CastarrColors.line, RoundedCornerShape(18.dp))
            .padding(8.dp),
        verticalArrangement = Arrangement.Center,
    ) {
        Column(
            Modifier
                .clip(RoundedCornerShape(12.dp))
                .background(androidx.compose.ui.graphics.Color(0xFFF4F6F7))
                .padding(10.dp),
        ) {
            Image(
                bitmap = bitmap.asImageBitmap(),
                contentDescription = "QR-Code zum Koppeln",
                modifier = Modifier.size(164.dp),
            )
        }
    }
}
