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.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.heightIn
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.Checkbox
import androidx.compose.material.CircularProgressIndicator
import androidx.compose.material.Divider
import androidx.compose.material.MaterialTheme
import androidx.compose.material.OutlinedButton
import androidx.compose.material.Text
import androidx.compose.material.TextButton
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
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.InternalTournamentStatsAgeOption
import de.tsschulz.tt_tagebuch.shared.api.models.InternalTournamentStatsDto
import de.tsschulz.tt_tagebuch.shared.i18n.MobileStrings

private fun allBandKeysFromOptions(options: List<InternalTournamentStatsAgeOption>): Set<String> {
    val seen = mutableSetOf<String>()
    val out = linkedSetOf<String>()
    for (o in options) {
        if (o.isNoClass == true) continue
        val bk = when {
            o.band == "adult" -> "adult"
            o.bandNum != null -> o.bandNum.toString()
            else -> continue
        }
        if (seen.add(bk)) out.add(bk)
    }
    return out
}

private fun effectiveAgeClassKeys(
    options: List<InternalTournamentStatsAgeOption>,
    selectedBandKeys: Set<String>,
    genderScope: String,
): List<String> {
    val valid = options.map { it.key }.toSet()
    val genderModes = if (genderScope == "female") listOf("female") else listOf("female", "open")
    val out = mutableListOf<String>()
    for (bk in selectedBandKeys) {
        for (g in genderModes) {
            val key = if (bk == "adult") "tt|adult|$g" else "tt|$bk|$g"
            if (key in valid) out.add(key)
        }
    }
    return out
}

private fun buildAgeClassKeysQuery(
    options: List<InternalTournamentStatsAgeOption>,
    selectedBandKeys: Set<String>,
    genderScope: String,
): String? {
    if (options.isEmpty()) return null
    val allKeys = options.map { it.key }.toSet()
    val effective = effectiveAgeClassKeys(options, selectedBandKeys, genderScope).toSet()
    if (effective.isEmpty()) return ""
    if (effective == allKeys) return null
    return effective.joinToString(",")
}

private fun bandOptionsForUi(options: List<InternalTournamentStatsAgeOption>): List<Pair<String, InternalTournamentStatsAgeOption>> {
    val byKey = linkedMapOf<String, InternalTournamentStatsAgeOption>()
    for (o in options) {
        if (o.isNoClass == true) continue
        val bandKey = if (o.band == "adult") "adult" else o.bandNum?.toString() ?: continue
        if (!byKey.containsKey(bandKey)) {
            byKey[bandKey] = o
        }
    }
    return byKey.entries.sortedWith(compareBy { (_, o) ->
        if (o.band == "adult") 1000 else o.bandNum ?: 0
    }).map { it.key to it.value }
}

private fun formatBandLabel(o: InternalTournamentStatsAgeOption, tr: (String, String) -> String): String {
    return when {
        o.band == "youth" && o.bandNum != null -> "J${o.bandNum}"
        o.band == "adult" -> tr("tournaments.internalStatsTtAdult", "Erwachsene")
        else -> o.bandNum?.toString() ?: ""
    }
}

@Composable
fun InternalTournamentStatsDialog(
    clubId: Int,
    dependencies: AppDependencies,
    onDismiss: () -> Unit,
) {
    val languageCode = LocalLanguageCode.current
    fun tr(key: String, fb: String) = MobileStrings.get(languageCode, key, fb)

    var months by remember { mutableStateOf(12) }
    var genderScope by remember { mutableStateOf("all") }
    var selectedBandKeys by remember { mutableStateOf<Set<String>>(emptySet()) }
    var bandsInitialized by remember { mutableStateOf(false) }

    var stats by remember { mutableStateOf<InternalTournamentStatsDto?>(null) }
    var loading by remember { mutableStateOf(true) }
    var error by remember { mutableStateOf<String?>(null) }

    val ageClassQuery = remember(stats, selectedBandKeys, genderScope) {
        val opts = stats?.ageClassOptions.orEmpty()
        buildAgeClassKeysQuery(opts, selectedBandKeys, genderScope)
    }

    LaunchedEffect(clubId, months, ageClassQuery) {
        loading = true
        error = null
        runCatching {
            dependencies.tournamentsApi.getInternalTournamentStats(clubId, months, ageClassQuery)
        }.fold(
            onSuccess = { data ->
                stats = data
                if (!bandsInitialized && data.ageClassOptions.isNotEmpty()) {
                    selectedBandKeys = allBandKeysFromOptions(data.ageClassOptions)
                    genderScope = "all"
                    bandsInitialized = true
                }
            },
            onFailure = { t ->
                error = t.message ?: tr("mobile.loadingError", "Fehler beim Laden")
                stats = null
            },
        )
        loading = false
    }

    val scroll = rememberScrollState()
    val s = stats

    StableAlertDialog(
        onDismissRequest = onDismiss,
        title = { Text(tr("tournaments.internalStatsTitle", "Interne Turnier-Statistik (Einzel)")) },
        text = {
            Column(
                modifier = Modifier
                    .heightIn(max = 520.dp)
                    .verticalScroll(scroll),
            ) {
                Row(
                    modifier = Modifier.fillMaxWidth(),
                    horizontalArrangement = Arrangement.spacedBy(8.dp),
                    verticalAlignment = Alignment.CenterVertically,
                ) {
                    listOf(
                        12 to tr("tournaments.internalStatsLast12Months", "Letzte 12 Monate"),
                        6 to tr("tournaments.internalStatsLast6Months", "Letzte 6 Monate"),
                        3 to tr("tournaments.internalStatsLast3Months", "Letzte 3 Monate"),
                    ).forEach { (m, fullLabel) ->
                        TextButton(
                            onClick = {
                                months = m
                                bandsInitialized = false
                                selectedBandKeys = emptySet()
                            },
                            enabled = !loading,
                        ) {
                            Text(
                                if (months == m) "✓ $fullLabel" else fullLabel,
                                style = MaterialTheme.typography.caption,
                                fontWeight = if (months == m) FontWeight.Bold else FontWeight.Normal,
                            )
                        }
                    }
                }
                if (loading) {
                    CircularProgressIndicator(modifier = Modifier.padding(16.dp).align(Alignment.CenterHorizontally))
                }
                error?.let {
                    Text(it, color = MaterialTheme.colors.error, modifier = Modifier.padding(vertical = 8.dp))
                }
                if (s != null && !loading) {
                    Text(
                        tr("tournaments.internalStatsTournamentsInPeriod", "{count} Turniere im Zeitraum.")
                            .replace("{count}", (s.tournamentCount).toString()),
                        style = MaterialTheme.typography.body2,
                        modifier = Modifier.padding(bottom = 6.dp),
                    )
                    Text(
                        tr("tournaments.internalStatsPointsExplain", "Punkte: Gruppenplatz als % plus K.-o.-Bonus."),
                        style = MaterialTheme.typography.caption,
                        color = MaterialTheme.colors.onSurface.copy(alpha = 0.75f),
                        modifier = Modifier.padding(bottom = 8.dp),
                    )
                    val bands = bandOptionsForUi(s.ageClassOptions)
                    if (bands.isNotEmpty()) {
                        Text(tr("tournaments.internalStatsAgeFilter", "Altersklassen"), fontWeight = FontWeight.SemiBold)
                        Row(modifier = Modifier.padding(vertical = 4.dp), horizontalArrangement = Arrangement.spacedBy(8.dp)) {
                            OutlinedButton(onClick = {
                                selectedBandKeys = allBandKeysFromOptions(s.ageClassOptions)
                                genderScope = "all"
                            }) { Text(tr("tournaments.internalStatsAgeSelectAll", "Alle"), style = MaterialTheme.typography.caption) }
                            OutlinedButton(onClick = { selectedBandKeys = emptySet() }) {
                                Text(tr("tournaments.internalStatsAgeSelectNone", "Keine"), style = MaterialTheme.typography.caption)
                            }
                        }
                        bands.forEach { (bandKey, opt) ->
                            Row(
                                verticalAlignment = Alignment.CenterVertically,
                                modifier = Modifier.fillMaxWidth(),
                            ) {
                                Checkbox(
                                    checked = bandKey in selectedBandKeys,
                                    onCheckedChange = { checked ->
                                        selectedBandKeys = if (checked) {
                                            selectedBandKeys + bandKey
                                        } else {
                                            selectedBandKeys - bandKey
                                        }
                                    },
                                )
                                Text(formatBandLabel(opt, ::tr))
                            }
                        }
                        Text(tr("tournaments.internalStatsFilterGenderColumn", "Geschlecht"), fontWeight = FontWeight.SemiBold, modifier = Modifier.padding(top = 8.dp))
                        Row(horizontalArrangement = Arrangement.spacedBy(8.dp)) {
                            TextButton(onClick = { genderScope = "all" }) {
                                Text(
                                    if (genderScope == "all") "✓ ${tr("tournaments.internalStatsGenderScopeAll", "Alle")}" else tr("tournaments.internalStatsGenderScopeAll", "Alle"),
                                    style = MaterialTheme.typography.caption,
                                )
                            }
                            TextButton(onClick = { genderScope = "female" }) {
                                Text(
                                    if (genderScope == "female") "✓ ${tr("tournaments.internalStatsGenderScopeGirls", "Mädchen/Frauen")}" else tr("tournaments.internalStatsGenderScopeGirls", "Mädchen/Frauen"),
                                    style = MaterialTheme.typography.caption,
                                )
                            }
                        }
                        Divider(modifier = Modifier.padding(vertical = 8.dp))
                    }
                    Text(tr("tournaments.internalStatsAbsoluteRank", "Absolut"), fontWeight = FontWeight.SemiBold)
                    if (s.absoluteRanking.isEmpty()) {
                        Text(tr("tournaments.internalStatsEmpty", "Keine Daten"), style = MaterialTheme.typography.caption)
                    } else {
                        s.absoluteRanking.take(40).forEachIndexed { i, r ->
                            Row(
                                modifier = Modifier
                                    .fillMaxWidth()
                                    .padding(vertical = 3.dp),
                                horizontalArrangement = Arrangement.SpaceBetween,
                            ) {
                                Text("${i + 1}. ${r.firstName.orEmpty()} ${r.lastName.orEmpty()}".trim(), modifier = Modifier.weight(1f))
                                Text(
                                    r.totalPoints?.let { v -> "%.2f".format(v) } ?: "–",
                                    fontWeight = FontWeight.Medium,
                                )
                            }
                        }
                    }
                    Spacer(modifier = Modifier.height(12.dp))
                    Text(tr("tournaments.internalStatsAverageRank", "Ø pro Turnier"), fontWeight = FontWeight.SemiBold)
                    if (s.averageRanking.isEmpty()) {
                        Text(tr("tournaments.internalStatsEmpty", "Keine Daten"), style = MaterialTheme.typography.caption)
                    } else {
                        s.averageRanking.take(40).forEachIndexed { i, r ->
                            Row(
                                modifier = Modifier
                                    .fillMaxWidth()
                                    .padding(vertical = 3.dp),
                                horizontalArrangement = Arrangement.SpaceBetween,
                            ) {
                                Text("${i + 1}. ${r.firstName.orEmpty()} ${r.lastName.orEmpty()}".trim(), modifier = Modifier.weight(1f))
                                Text(r.averagePoints?.toString() ?: "–", fontWeight = FontWeight.Medium)
                            }
                        }
                    }
                }
            }
        },
        confirmButton = {
            TextButton(onClick = onDismiss) {
                Text(tr("common.close", "Schließen"))
            }
        },
    )
}
