package de.tsschulz.tt_tagebuch.app.ui

import androidx.compose.foundation.layout.Arrangement
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.lazy.LazyColumn
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.Button
import androidx.compose.material.CircularProgressIndicator
import androidx.compose.material.Divider
import androidx.compose.material.Icon
import androidx.compose.material.IconButton
import androidx.compose.material.MaterialTheme
import androidx.compose.material.OutlinedTextField
import androidx.compose.material.Scaffold
import androidx.compose.material.Switch
import androidx.compose.material.Tab
import androidx.compose.material.TabRow
import androidx.compose.material.Text
import androidx.compose.material.TextButton
import androidx.compose.material.TopAppBar
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.ArrowBack
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableIntStateOf
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import de.tsschulz.tt_tagebuch.app.AppDependencies
import de.tsschulz.tt_tagebuch.shared.api.models.InternalTournamentDetailDto
import de.tsschulz.tt_tagebuch.shared.api.models.SetTournamentModusBody
import de.tsschulz.tt_tagebuch.shared.api.models.TournamentClassDto
import de.tsschulz.tt_tagebuch.shared.api.models.TournamentClubTournamentBody
import de.tsschulz.tt_tagebuch.shared.api.models.TournamentCreateGroupMatchesBody
import de.tsschulz.tt_tagebuch.shared.api.models.TournamentCreateGroupsBody
import de.tsschulz.tt_tagebuch.shared.api.models.TournamentExternalParticipantRowDto
import de.tsschulz.tt_tagebuch.shared.api.models.TournamentGetExternalParticipantsBody
import de.tsschulz.tt_tagebuch.shared.api.models.TournamentGetParticipantsBody
import de.tsschulz.tt_tagebuch.shared.api.models.TournamentMatchDto
import de.tsschulz.tt_tagebuch.shared.api.models.TournamentParticipantRowDto
import de.tsschulz.tt_tagebuch.shared.api.models.UpdateTournamentMetaBody
import de.tsschulz.tt_tagebuch.shared.i18n.MobileStrings
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import kotlinx.serialization.json.JsonElement
import kotlinx.serialization.json.JsonArray
import kotlinx.serialization.json.jsonObject
import kotlinx.serialization.json.jsonPrimitive
import kotlinx.serialization.json.contentOrNull
import android.util.Log
import androidx.compose.ui.focus.onFocusChanged
import androidx.compose.ui.focus.FocusState

/**
 * Vollständiger Turnier-Workspace (analog Web [TournamentTab]): Stammdaten, Ablauf/Gruppen,
 * Klassen, Teilnehmer, Spiele, Doppel-Paarungen. Lädt und speichert über [de.tsschulz.tt_tagebuch.shared.api.TournamentsApi].
 */
@Composable
internal fun InternalTournamentEditorScreen(
    clubId: Int,
    tournamentId: Int,
    dependencies: AppDependencies,
    onClose: () -> Unit,
) {
    val languageCode = LocalLanguageCode.current
    fun tr(key: String, fb: String) = MobileStrings.get(languageCode, key, fb)
    val api = dependencies.tournamentsApi
    val scope = dependencies.applicationScope

    var loading by remember { mutableStateOf(true) }
    var error by remember { mutableStateOf<String?>(null) }
    var detail by remember { mutableStateOf<InternalTournamentDetailDto?>(null) }
    var classes by remember { mutableStateOf<List<TournamentClassDto>>(emptyList()) }
    var participants by remember { mutableStateOf<List<TournamentParticipantRowDto>>(emptyList()) }
    var externalParticipants by remember { mutableStateOf<List<TournamentExternalParticipantRowDto>>(emptyList()) }
    var matches by remember { mutableStateOf<List<TournamentMatchDto>>(emptyList()) }
    var groupsJson by remember { mutableStateOf<JsonElement?>(null) }

    var tabIndex by remember { mutableIntStateOf(0) }
    val showPairingsTab = detail?.isDoublesTournament == true
    val tabTitles = remember(showPairingsTab, languageCode) {
        buildList {
            // Match web ordering: Config, Participants, Groups, Results, Placements, (Pairings)
            add(tr("tournaments.tabConfig", "Konfiguration"))
            add(tr("tournaments.tabParticipants", "Teilnehmer"))
            add(tr("tournaments.tabGroups", "Gruppen"))
            add(tr("tournaments.tabResults", "Ergebnisse"))
            add(tr("tournaments.tabPlacements", "Platzierungen"))
            if (showPairingsTab) add(tr("tournaments.pairings", "Doppel-Paarungen"))
        }
    }

    fun reloadAll() {
        scope.launch {
            loading = true
            error = null
            runCatching {
                withContext(Dispatchers.IO) {
                    val d = api.getTournament(clubId, tournamentId)
                    val c = api.listTournamentClasses(clubId, tournamentId)
                    val p = api.listInternalParticipants(
                        TournamentGetParticipantsBody(clubId, tournamentId, classId = null),
                    )
                    val e = api.listExternalParticipants(
                        TournamentGetExternalParticipantsBody(clubId, tournamentId, classId = null),
                    )
                    val m = api.listMatches(clubId, tournamentId)
                    val g = api.getGroups(clubId, tournamentId)
                    TournamentEditorLoadResult(d, c, p, e, m, g)
                }
            }.fold(
                onSuccess = { r ->
                            detail = r.detail
                            try {
                                Log.d("InternalTournamentEditor", "Loaded detail.numberOfTables=${'$'}{r.detail.numberOfTables}")
                            } catch (e: Exception) {
                                // ignore
                            }
                    classes = r.classes
                    participants = r.participants
                    externalParticipants = r.external
                    matches = r.matches
                    groupsJson = r.groups
                },
                onFailure = { t ->
                    error = t.message ?: tr("mobile.loadingError", "Fehler beim Laden")
                },
            )
            loading = false
        }
    }

    LaunchedEffect(clubId, tournamentId) {
        reloadAll()
    }

    Scaffold(
        topBar = {
            TopAppBar(
                title = {
                    Text(
                        detail?.name ?: tr("mobile.tournamentEditorTitle", "Turnier bearbeiten"),
                        maxLines = 1,
                    )
                },
                navigationIcon = {
                    IconButton(onClick = onClose) {
                        Icon(Icons.AutoMirrored.Filled.ArrowBack, contentDescription = tr("mobile.back", "Zurück"))
                    }
                },
            )
        },
    ) { padding ->
        Column(
            modifier = Modifier
                .fillMaxSize()
                .padding(padding),
        ) {
            if (error != null) {
                Text(error!!, color = MaterialTheme.colors.error, modifier = Modifier.padding(16.dp))
                TextButton(onClick = { reloadAll() }) {
                    Text(tr("mobile.retry", "Erneut versuchen"))
                }
            }
            if (loading && detail == null) {
                CircularProgressIndicator(modifier = Modifier.padding(24.dp).align(Alignment.CenterHorizontally))
                return@Column
            }
            val d = detail ?: return@Column

            TabRow(
                selectedTabIndex = tabIndex.coerceAtMost(tabTitles.lastIndex),
                modifier = Modifier.fillMaxWidth(),
            ) {
                tabTitles.forEachIndexed { i, title ->
                    Tab(
                        selected = tabIndex == i,
                        onClick = { tabIndex = i },
                        text = { Text(title, maxLines = 1) },
                    )
                }
            }
            Divider()

            when (tabIndex) {
                // 0: Config (Meta with integrated Classes management)
                0 -> TournamentEditorMetaTab(
                    clubId = clubId,
                    tournamentId = tournamentId,
                    detail = d,
                    classes = classes,
                    tr = ::tr,
                    api = api,
                    scope = scope,
                    onSave = { body ->
                        scope.launch {
                            runCatching {
                                withContext(Dispatchers.IO) {
                                    api.updateTournament(clubId, tournamentId, body)
                                }
                            }.fold(
                                onSuccess = { detail = it },
                                onFailure = { error = it.message },
                            )
                            reloadAll()
                        }
                    },
                    onReload = { reloadAll() },
                    onError = { error = it },
                )
                // 1: Participants (web's second tab)
                1 -> Column(Modifier.fillMaxSize().verticalScroll(rememberScrollState()).padding(16.dp)) {
                    TournamentEditorParticipantsTab(
                        clubId = clubId,
                        tournamentId = tournamentId,
                        classes = classes,
                        participants = participants,
                        externalParticipants = externalParticipants,
                        tournamentDate = d.date,
                        dependencies = dependencies,
                        tr = ::tr,
                        onReload = { reloadAll() },
                        onError = { error = it },
                    )
                }
                // 2: Groups / Flow
                2 -> TournamentEditorFlowTab(
                    clubId = clubId,
                    tournamentId = tournamentId,
                    detail = d,
                    groupsJson = groupsJson,
                    tr = ::tr,
                    api = api,
                    scope = scope,
                    onReload = { reloadAll() },
                    onError = { error = it },
                )
                // 3: Results / Matches
                3 -> Column(Modifier.fillMaxSize().verticalScroll(rememberScrollState()).padding(16.dp)) {
                    TournamentEditorMatchesTab(
                        clubId = clubId,
                        tournamentId = tournamentId,
                        matches = matches,
                        winningSets = d.winningSets ?: 3,
                        detail = d,
                        groupsJson = groupsJson,
                        tr = ::tr,
                        api = api,
                        scope = scope,
                        onReload = { reloadAll() },
                        onError = { error = it },
                    )
                }
                // 4: Placements (placeholder for now)
                4 -> TournamentEditorPlacementsTab(
                    tr = ::tr,
                )
                // 5: Pairings (optional)
                5 -> if (showPairingsTab) {
                    Column(Modifier.fillMaxSize().verticalScroll(rememberScrollState()).padding(16.dp)) {
                        TournamentEditorPairingsTab(
                            clubId = clubId,
                            tournamentId = tournamentId,
                            classes = classes,
                            participants = participants,
                            externalParticipants = externalParticipants,
                            tr = ::tr,
                            api = api,
                            scope = scope,
                            onReload = { reloadAll() },
                            onError = { error = it },
                        )
                    }
                } else {
                    Spacer(Modifier.height(16.dp))
                }
            }
        }
    }
}

@Composable
private fun TournamentEditorPlacementsTab(
    tr: (String, String) -> String,
) {
    Column(
        modifier = Modifier
            .fillMaxSize()
            .padding(16.dp),
        verticalArrangement = Arrangement.Center,
        horizontalAlignment = Alignment.CenterHorizontally,
    ) {
        Text(tr("tournaments.placementsPendingTitle", "Platzierungen noch nicht verfügbar"), fontWeight = FontWeight.SemiBold)
        Spacer(modifier = Modifier.height(8.dp))
        Text(tr("tournaments.noPlacementsYet", "Noch keine Platzierungen vorhanden."))
    }
}

private data class TournamentEditorLoadResult(
    val detail: InternalTournamentDetailDto,
    val classes: List<TournamentClassDto>,
    val participants: List<TournamentParticipantRowDto>,
    val external: List<TournamentExternalParticipantRowDto>,
    val matches: List<TournamentMatchDto>,
    val groups: JsonElement,
)

@Composable
private fun TournamentEditorMetaTab(
    clubId: Int,
    tournamentId: Int,
    detail: InternalTournamentDetailDto,
    classes: List<TournamentClassDto>,
    tr: (String, String) -> String,
    api: de.tsschulz.tt_tagebuch.shared.api.TournamentsApi,
    scope: kotlinx.coroutines.CoroutineScope,
    onSave: (UpdateTournamentMetaBody) -> Unit,
    onReload: () -> Unit,
    onError: (String?) -> Unit,
) {
    var name by remember(detail.id) { mutableStateOf(detail.name.orEmpty()) }
    var date by remember(detail.id) { mutableStateOf(detail.date.orEmpty()) }
    var winningSets by remember(detail.id) { mutableStateOf((detail.winningSets ?: 3).toString()) }
    var tables by remember(detail.id) { mutableStateOf(detail.numberOfTables?.toString().orEmpty()) }
    var doubles by remember(detail.id) { mutableStateOf(detail.isDoublesTournament == true) }
    // Snapshot of last saved values to avoid repeated identical saves
    val lastSaved = remember(detail.id) {
        mutableStateOf(
            UpdateTournamentMetaBody(
                name = detail.name,
                date = detail.date,
                winningSets = detail.winningSets,
                numberOfTables = detail.numberOfTables,
                isDoublesTournament = detail.isDoublesTournament,
            ),
        )
    }
    var showClasses by remember { mutableStateOf(false) }

    Column(
        modifier = Modifier
            .fillMaxSize()
            .verticalScroll(rememberScrollState())
            .padding(16.dp),
        verticalArrangement = Arrangement.spacedBy(12.dp),
    ) {
        Column(verticalArrangement = Arrangement.spacedBy(8.dp)) {
            Text(tr("tournaments.metaSectionTitle", "Stammdaten"), style = MaterialTheme.typography.h6, fontWeight = FontWeight.SemiBold)
            Spacer(modifier = Modifier.height(8.dp))
            Text(tr("tournaments.tournamentName", "Turniername"), fontWeight = FontWeight.SemiBold)
            OutlinedTextField(
                value = name,
                onValueChange = { name = it },
                modifier = Modifier.fillMaxWidth().onFocusChanged { fs: FocusState -> if (!fs.isFocused) saveIfChanged(name, date, winningSets, tables, doubles, lastSaved, onSave) },
                singleLine = true,
            )
            LocalizedDatePickerField(
                value = date,
                onValueChange = {
                    date = it
                    saveIfChanged(name, it, winningSets, tables, doubles, lastSaved, onSave)
                },
                label = tr("tournaments.date", "Datum"),
                modifier = Modifier.fillMaxWidth(),
            )
            OutlinedTextField(
                value = winningSets,
                onValueChange = { winningSets = it.filter { ch -> ch.isDigit() }.take(2) },
                modifier = Modifier.fillMaxWidth().onFocusChanged { fs: FocusState -> if (!fs.isFocused) saveIfChanged(name, date, winningSets, tables, doubles, lastSaved, onSave) },
                label = { Text(tr("tournaments.winningSets", "Gewinnsätze")) },
                singleLine = true,
            )
            OutlinedTextField(
                value = tables,
                onValueChange = { tables = it.filter { ch -> ch.isDigit() } },
                modifier = Modifier.fillMaxWidth().onFocusChanged { fs: FocusState -> if (!fs.isFocused) saveIfChanged(name, date, winningSets, tables, doubles, lastSaved, onSave) },
                label = { Text(tr("tournaments.numberOfTables", "Tische")) },
                singleLine = true,
            )
            Row(verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.SpaceBetween, modifier = Modifier.fillMaxWidth()) {
                Text(tr("mobile.doublesTournament", "Doppel-Turnier"))
                Switch(checked = doubles, onCheckedChange = {
                    doubles = it
                    saveIfChanged(name, date, winningSets, tables, doubles, lastSaved, onSave)
                })
            }
            Button(
                onClick = {
                    saveIfChanged(name, date, winningSets, tables, doubles, lastSaved, onSave, force = true)
                },
                modifier = Modifier.fillMaxWidth(),
            ) {
                Text(tr("mobile.save", "Speichern"))
            }
            Divider(modifier = Modifier.padding(vertical = 12.dp))
            Row(horizontalArrangement = Arrangement.SpaceBetween, modifier = Modifier.fillMaxWidth()) {
                Text(tr("tournaments.classesSection", "Klassen"), style = MaterialTheme.typography.subtitle1, fontWeight = FontWeight.SemiBold)
                TextButton(onClick = { showClasses = !showClasses }) {
                    Text(if (showClasses) tr("mobile.hide", "Verbergen") else tr("mobile.show", "Anzeigen"))
                }
            }
            Spacer(modifier = Modifier.height(6.dp))
        }
        if (showClasses) {
            TournamentEditorClassesTab(
                clubId = clubId,
                tournamentId = tournamentId,
                classes = classes,
                tr = tr,
                api = api,
                scope = scope,
                onReload = onReload,
                onError = onError,
            )
        }
    }
}

private fun saveIfChanged(
    name: String,
    date: String,
    winningSets: String,
    tables: String,
    doubles: Boolean,
    lastSaved: androidx.compose.runtime.MutableState<UpdateTournamentMetaBody>,
    onSave: (UpdateTournamentMetaBody) -> Unit,
    force: Boolean = false,
) {
    val ws = winningSets.toIntOrNull()?.coerceAtLeast(1) ?: 3
    val nt = tables.toIntOrNull()
    val newBody = UpdateTournamentMetaBody(
        name = name.ifBlank { null },
        date = date.ifBlank { null },
        winningSets = ws,
        numberOfTables = nt,
        isDoublesTournament = doubles,
    )
    if (!force && newBody == lastSaved.value) return
    try {
        Log.d("InternalTournamentEditor", "saveIfChanged -> saving body: $newBody")
    } catch (e: Exception) {
        // ignore
    }
    onSave(newBody)
    lastSaved.value = newBody
}

@Composable
private fun TournamentEditorFlowTab(
    clubId: Int,
    tournamentId: Int,
    detail: InternalTournamentDetailDto,
    groupsJson: JsonElement?,
    tr: (String, String) -> String,
    api: de.tsschulz.tt_tagebuch.shared.api.TournamentsApi,
    scope: kotlinx.coroutines.CoroutineScope,
    onReload: () -> Unit,
    onError: (String?) -> Unit,
) {
    val isGroups = detail.type == "groups"
    var isGroupMode by remember(detail.id, detail.type) { mutableStateOf(isGroups) }
    var numGroups by remember(detail.id) { mutableStateOf((detail.numberOfGroups?.takeIf { it > 0 } ?: 1).toString()) }
    var adv by remember(detail.id) { mutableStateOf((detail.advancingPerGroup ?: 1).toString()) }
    var createGroupsInput by remember { mutableStateOf(numGroups) }
    val scroll = rememberScrollState()

    Column(
        modifier = Modifier
            .fillMaxSize()
            .verticalScroll(scroll)
            .padding(16.dp),
        verticalArrangement = Arrangement.spacedBy(12.dp),
    ) {
        Text(tr("tournaments.tournamentMode", "Turniermodus"), fontWeight = FontWeight.SemiBold)
        Row(horizontalArrangement = Arrangement.spacedBy(8.dp), verticalAlignment = Alignment.CenterVertically) {
            Text(tr("tournaments.groupPhase", "Gruppenphase"))
            Switch(
                checked = isGroupMode,
                onCheckedChange = { isGroupMode = it },
            )
        }
        OutlinedTextField(
            value = numGroups,
            onValueChange = { numGroups = it.filter { ch -> ch.isDigit() }.take(2) },
            label = { Text(tr("mobile.groups", "Gruppen")) },
            modifier = Modifier.fillMaxWidth(),
            singleLine = true,
        )
        OutlinedTextField(
            value = adv,
            onValueChange = { adv = it.filter { ch -> ch.isDigit() }.take(2) },
            label = { Text(tr("tournaments.advancingPerGroup", "Weiterkommende pro Gruppe")) },
            modifier = Modifier.fillMaxWidth(),
            singleLine = true,
        )
        Button(
            onClick = {
                val n = numGroups.toIntOrNull()?.coerceAtLeast(1) ?: 1
                val a = adv.toIntOrNull()?.coerceAtLeast(1) ?: 1
                scope.launch {
                    runCatching {
                        kotlinx.coroutines.withContext(Dispatchers.IO) {
                            api.setModus(
                                SetTournamentModusBody(
                                    clubId = clubId,
                                    tournamentId = tournamentId,
                                    type = if (isGroupMode) "groups" else "knockout",
                                    numberOfGroups = n,
                                    advancingPerGroup = a,
                                ),
                            )
                        }
                    }.onFailure { onError(it.message) }
                    onReload()
                }
            },
            modifier = Modifier.fillMaxWidth(),
        ) {
            Text(tr("mobile.apply", "Übernehmen"))
        }
        Divider(modifier = Modifier.padding(vertical = 8.dp))
        Text(tr("mobile.tournamentGroupActions", "Gruppen-Aktionen"), fontWeight = FontWeight.SemiBold)
        OutlinedTextField(
            value = createGroupsInput,
            onValueChange = { createGroupsInput = it.filter { ch -> ch.isDigit() }.take(2) },
            label = { Text(tr("tournaments.numberOfGroupsShort", "Anzahl Gruppen")) },
            modifier = Modifier.fillMaxWidth(),
            singleLine = true,
        )
        Row(horizontalArrangement = Arrangement.spacedBy(8.dp)) {
            TextButton(
                onClick = {
                    val n = createGroupsInput.toIntOrNull()
                    scope.launch {
                        runCatching {
                            kotlinx.coroutines.withContext(Dispatchers.IO) {
                                api.createEmptyGroups(
                                    TournamentCreateGroupsBody(clubId, tournamentId, n),
                                )
                            }
                        }.onFailure { onError(it.message) }
                        onReload()
                    }
                },
            ) { Text(tr("tournaments.createEmptyGroups", "Leere Gruppen")) }
            TextButton(
                onClick = {
                    scope.launch {
                        runCatching {
                            kotlinx.coroutines.withContext(Dispatchers.IO) {
                                api.fillGroups(TournamentClubTournamentBody(clubId, tournamentId))
                            }
                        }.onFailure { onError(it.message) }
                        onReload()
                    }
                },
            ) { Text(tr("tournaments.fillGroups", "Aufteilen")) }
        }
        TextButton(
            onClick = {
                scope.launch {
                    runCatching {
                        kotlinx.coroutines.withContext(Dispatchers.IO) {
                            api.createGroupMatches(
                                TournamentCreateGroupMatchesBody(clubId, tournamentId, classId = null),
                            )
                        }
                    }.onFailure { onError(it.message) }
                    onReload()
                }
            },
            modifier = Modifier.fillMaxWidth(),
        ) { Text(tr("tournaments.createGroupMatches", "Gruppenspiele erstellen")) }
        Row(horizontalArrangement = Arrangement.spacedBy(8.dp)) {
            TextButton(
                onClick = {
                    scope.launch {
                        runCatching {
                            kotlinx.coroutines.withContext(Dispatchers.IO) {
                                api.resetGroups(TournamentClubTournamentBody(clubId, tournamentId))
                            }
                        }.onFailure { onError(it.message) }
                        onReload()
                    }
                },
            ) { Text(tr("tournaments.resetGroups", "Gruppen zurücksetzen")) }
            TextButton(
                onClick = {
                    scope.launch {
                        runCatching {
                            kotlinx.coroutines.withContext(Dispatchers.IO) {
                                api.resetMatches(TournamentClubTournamentBody(clubId, tournamentId))
                            }
                        }.onFailure { onError(it.message) }
                        onReload()
                    }
                },
            ) { Text(tr("tournaments.resetMatches", "Spiele zurücksetzen")) }
        }
        // K.-o.-Runde starten: verschoben (nicht in Gruppen-Tab)
        Text(
            tr("mobile.tournamentGroupsPreview", "Gruppen-Daten (Überblick)"),
            style = MaterialTheme.typography.caption,
            color = MaterialTheme.colors.onSurface.copy(alpha = 0.75f),
        )

        when (groupsJson) {
            is JsonArray -> {
                val arr = groupsJson as JsonArray
                if (arr.isEmpty()) {
                    Text(tr("mobile.noGroups", "Keine Gruppen vorhanden"))
                } else {
                    arr.forEach { gElem ->
                        val obj = gElem.jsonObject
                        val classIdVal = obj["classId"]?.jsonPrimitive?.contentOrNull?.toIntOrNull()
                        val groupNumber = obj["groupNumber"]?.jsonPrimitive?.contentOrNull?.toIntOrNull() ?: 0
                        Text(
                            (classIdVal?.toString() ?: "—") + " — " + tr("tournaments.group", "Gruppe") + " ${groupNumber}",
                            fontWeight = FontWeight.SemiBold,
                        )
                        val participantsElem = obj["participants"]
                            if (participantsElem is JsonArray) {
                                // Table header
                                Row(Modifier.fillMaxWidth()) {
                                    Text("#", fontWeight = FontWeight.SemiBold, modifier = Modifier.weight(0.08f))
                                    Text(tr("tournaments.participant", "Teilnehmer"), fontWeight = FontWeight.SemiBold, modifier = Modifier.weight(0.62f))
                                    Text(tr("tournaments.sets", "Sätze"), fontWeight = FontWeight.SemiBold, modifier = Modifier.weight(0.15f))
                                    Text(tr("tournaments.points", "Punkte"), fontWeight = FontWeight.SemiBold, modifier = Modifier.weight(0.15f))
                                }
                                Spacer(modifier = Modifier.height(6.dp))
                                participantsElem.forEach { p ->
                                    val pObj = p.jsonObject
                                    val pname = pObj["name"]?.jsonPrimitive?.contentOrNull ?: "?"
                                    val pos = pObj["position"]?.jsonPrimitive?.contentOrNull ?: "-"
                                    val setsWon = pObj["setsWon"]?.jsonPrimitive?.contentOrNull ?: "-"
                                    val setsLost = pObj["setsLost"]?.jsonPrimitive?.contentOrNull ?: "-"
                                    val pointsWon = pObj["pointsWon"]?.jsonPrimitive?.contentOrNull ?: "-"
                                    val pointsLost = pObj["pointsLost"]?.jsonPrimitive?.contentOrNull ?: "-"
                                    Row(Modifier.fillMaxWidth()) {
                                        Text(pos, modifier = Modifier.weight(0.08f))
                                        Text(pname, modifier = Modifier.weight(0.62f))
                                        Text("${setsWon}:${setsLost}", modifier = Modifier.weight(0.15f))
                                        Text("${pointsWon}:${pointsLost}", modifier = Modifier.weight(0.15f))
                                    }
                                }
                            } else {
                                Text(tr("mobile.noGroupParticipants", "Keine Teilnehmer"))
                            }
                        Divider(modifier = Modifier.padding(vertical = 8.dp))
                    }
                }
            }
            null -> Text("—")
            else -> Text(tr("mobile.dataLoaded", "geladen"))
        }
    }
}
