package de.tsschulz.tt_tagebuch.app.ui

import androidx.activity.compose.BackHandler
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.heightIn
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.verticalScroll
import androidx.compose.material.Button
import androidx.compose.material.Card
import androidx.compose.material.CircularProgressIndicator
import androidx.compose.material.Divider
import androidx.compose.material.DropdownMenu
import androidx.compose.material.DropdownMenuItem
import androidx.compose.material.Icon
import androidx.compose.material.IconButton
import androidx.compose.material.MaterialTheme
import androidx.compose.material.OutlinedButton
import androidx.compose.material.OutlinedTextField
import androidx.compose.material.Switch
import androidx.compose.material.Text
import androidx.compose.material.TextButton
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.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.text.font.FontWeight
import androidx.compose.ui.unit.dp
import de.tsschulz.tt_tagebuch.app.AppDependencies
import de.tsschulz.tt_tagebuch.shared.api.PredefinedActivitiesApi
import de.tsschulz.tt_tagebuch.shared.api.models.MemberTransferConfigEnvelope
import de.tsschulz.tt_tagebuch.shared.api.models.MemberTransferConfigSaveBody
import de.tsschulz.tt_tagebuch.shared.api.models.PredefinedActivityDto
import de.tsschulz.tt_tagebuch.shared.api.models.PredefinedActivityUpsertBody
import de.tsschulz.tt_tagebuch.shared.api.models.TrainingGroupDto
import de.tsschulz.tt_tagebuch.shared.api.models.TrainingTimeDto
import de.tsschulz.tt_tagebuch.shared.api.models.UpdateClubSettingsBody
import de.tsschulz.tt_tagebuch.shared.api.models.UpdateTrainingTimeBody
import de.tsschulz.tt_tagebuch.shared.api.models.canReadClubSettings
import de.tsschulz.tt_tagebuch.shared.api.models.canReadMembers
import de.tsschulz.tt_tagebuch.shared.api.models.canReadPredefinedActivities
import de.tsschulz.tt_tagebuch.shared.api.models.canWriteMembers
import de.tsschulz.tt_tagebuch.shared.api.models.canWritePredefinedActivities
import de.tsschulz.tt_tagebuch.shared.api.models.displayLabel
import de.tsschulz.tt_tagebuch.shared.i18n.MobileStrings
import kotlinx.coroutines.launch
import kotlinx.serialization.json.JsonPrimitive
import kotlinx.serialization.json.buildJsonObject

private val StammdatenPad = 20.dp
private val StammdatenTouchMin = 48.dp

internal enum class ClubStammdatenSection {
    ClubSettings,
    PredefinedActivities,
    MemberTransfer,
    Teams,
}

@Composable
internal fun ClubStammdatenFlowScreen(
    destination: ClubStammdatenSection,
    dependencies: AppDependencies,
    onBack: () -> Unit,
) {
    BackHandler(onBack = onBack)
    when (destination) {
        ClubStammdatenSection.ClubSettings -> MobileClubSettingsScreen(dependencies, onBack)
        ClubStammdatenSection.PredefinedActivities -> MobilePredefinedActivitiesScreen(dependencies, onBack)
        ClubStammdatenSection.MemberTransfer -> MobileMemberTransferScreen(dependencies, onBack)
        ClubStammdatenSection.Teams -> TeamManagementScreen(dependencies, onBack)
    }
}

@Composable
private fun StammdatenTopBar(title: String, onBack: () -> Unit) {
    Row(
        modifier = Modifier.fillMaxWidth(),
        verticalAlignment = Alignment.CenterVertically,
    ) {
        IconButton(onClick = onBack) {
            Icon(Icons.AutoMirrored.Filled.ArrowBack, contentDescription = null)
        }
        Text(title, style = MaterialTheme.typography.h6, fontWeight = FontWeight.SemiBold)
    }
    Spacer(modifier = Modifier.height(8.dp))
}

@Composable
private fun MobilePredefinedActivitiesScreen(dependencies: AppDependencies, onBack: () -> Unit) {
    val languageCode = LocalLanguageCode.current
    fun tr(key: String, fb: String) = MobileStrings.get(languageCode, key, fb)
    val clubState by dependencies.clubManager.state.collectAsState()
    val clubId = clubState.currentClubId ?: return
    val perms = clubState.currentPermissions
    val scope = rememberCoroutineScope()
    var list by remember { mutableStateOf<List<PredefinedActivityDto>>(emptyList()) }
    var loading by remember { mutableStateOf(true) }
    var error by remember { mutableStateOf<String?>(null) }
    var refresh by remember { mutableStateOf(0) }
    var editorTarget by remember { mutableStateOf<PredefinedActivityDto?>(null) }
    var creatingNew by remember { mutableStateOf(false) }

    LaunchedEffect(clubId, refresh) {
        loading = true
        error = null
        list = runCatching { dependencies.predefinedActivitiesApi.list(scope = null) }
            .onFailure { error = it.message }
            .getOrDefault(emptyList())
        loading = false
    }

    Column(modifier = Modifier.fillMaxSize().padding(StammdatenPad)) {
        StammdatenTopBar(tr("mobile.predefinedActivities", "Standard-Aktivitäten"), onBack)
        if (perms?.canReadPredefinedActivities() != true) {
            Text(tr("mobile.noAccess", "Keine Berechtigung."))
            return@Column
        }
        if (perms.canWritePredefinedActivities()) {
            Button(
                onClick = { creatingNew = true },
                modifier = Modifier
                    .fillMaxWidth()
                    .padding(top = 8.dp)
                    .heightIn(min = StammdatenTouchMin),
            ) { Text(tr("mobile.newPredefined", "Neue Aktivität")) }
        }
        when {
            loading -> CircularProgressIndicator(modifier = Modifier.padding(top = 24.dp))
            error != null -> Text(error!!, color = MaterialTheme.colors.error)
            else -> {
                LazyColumn(
                    modifier = Modifier.fillMaxSize().padding(top = 8.dp),
                    verticalArrangement = Arrangement.spacedBy(6.dp),
                ) {
                    items(list, key = { it.id }) { a ->
                        Card(modifier = Modifier.fillMaxWidth(), elevation = 1.dp) {
                            TextButton(
                                onClick = { editorTarget = a },
                                enabled = perms.canWritePredefinedActivities(),
                                modifier = Modifier.fillMaxWidth().heightIn(min = StammdatenTouchMin),
                            ) {
                                Column(modifier = Modifier.fillMaxWidth(), horizontalAlignment = Alignment.Start) {
                                    Text(a.displayLabel(), fontWeight = FontWeight.SemiBold)
                                    a.code?.takeIf { it.isNotBlank() }?.let { Text(it, style = MaterialTheme.typography.caption) }
                                }
                            }
                        }
                    }
                }
            }
        }
    }

    if (editorTarget != null || creatingNew) {
        PredefinedActivityEditorDialog(
            initial = editorTarget,
            isNew = creatingNew,
            canSave = perms?.canWritePredefinedActivities() == true,
            onDismiss = { editorTarget = null; creatingNew = false },
            onSaved = {
                editorTarget = null
                creatingNew = false
                refresh++
            },
            resolve = { k, fb -> tr(k, fb) },
            scope = scope,
            api = dependencies.predefinedActivitiesApi,
        )
    }
}

@Composable
private fun PredefinedActivityEditorDialog(
    initial: PredefinedActivityDto?,
    isNew: Boolean,
    canSave: Boolean,
    onDismiss: () -> Unit,
    onSaved: () -> Unit,
    resolve: (String, String) -> String,
    scope: kotlinx.coroutines.CoroutineScope,
    api: PredefinedActivitiesApi,
) {
    var name by remember(initial?.id, isNew) { mutableStateOf(initial?.name.orEmpty()) }
    var code by remember(initial?.id, isNew) { mutableStateOf(initial?.code.orEmpty()) }
    var description by remember(initial?.id, isNew) { mutableStateOf(initial?.description.orEmpty()) }
    var durationText by remember(initial?.id, isNew) { mutableStateOf(initial?.durationText.orEmpty()) }
    var duration by remember(initial?.id, isNew) { mutableStateOf(initial?.duration?.toString().orEmpty()) }
    var exclude by remember(initial?.id, isNew) { mutableStateOf(initial?.excludeFromStats == true) }
    var err by remember { mutableStateOf<String?>(null) }
    var busy by remember { mutableStateOf(false) }

    StableAlertDialog(
        onDismissRequest = onDismiss,
        title = { Text(if (isNew) resolve("mobile.newPredefined", "Neue Aktivität") else resolve("mobile.editPredefined", "Bearbeiten")) },
        text = {
            Column(verticalArrangement = Arrangement.spacedBy(8.dp)) {
                err?.let { Text(it, color = MaterialTheme.colors.error) }
                OutlinedTextField(value = name, onValueChange = { name = it }, label = { Text(resolve("tournaments.name", "Name")) })
                OutlinedTextField(value = code, onValueChange = { code = it }, label = { Text("Code") })
                OutlinedTextField(
                    value = description,
                    onValueChange = { description = it },
                    label = { Text(resolve("mobile.description", "Beschreibung")) },
                    minLines = 2,
                )
                OutlinedTextField(value = durationText, onValueChange = { durationText = it }, label = { Text("Dauer (Text)") })
                OutlinedTextField(value = duration, onValueChange = { duration = it.filter { ch -> ch.isDigit() } }, label = { Text("Dauer (Min)") })
                RowSwitch(resolve("mobile.excludeFromStats", "Von Statistik ausschließen"), exclude) { exclude = it }
            }
        },
        confirmButton = {
            TextButton(
                enabled = canSave && !busy && name.isNotBlank(),
                onClick = {
                    scope.launch {
                        busy = true
                        err = null
                        val d = duration.toIntOrNull()
                        val body = PredefinedActivityUpsertBody(
                            name = name.trim(),
                            code = code.trim().ifBlank { null },
                            description = description.trim().ifBlank { null },
                            durationText = durationText.trim().ifBlank { null },
                            duration = d,
                            excludeFromStats = exclude,
                        )
                        runCatching {
                            if (isNew) {
                                api.create(body)
                            } else {
                                api.update(initial!!.id, body)
                            }
                            onSaved()
                        }.onFailure { err = it.message }
                        busy = false
                    }
                },
            ) { Text(resolve("common.save", "Speichern")) }
        },
        dismissButton = {
            TextButton(onClick = onDismiss) { Text(resolve("common.cancel", "Abbrechen")) }
        },
    )
}

@Composable
private fun MobileMemberTransferScreen(dependencies: AppDependencies, onBack: () -> Unit) {
    val languageCode = LocalLanguageCode.current
    fun tr(key: String, fb: String) = MobileStrings.get(languageCode, key, fb)
    val clubState by dependencies.clubManager.state.collectAsState()
    val clubId = clubState.currentClubId ?: return
    val perms = clubState.currentPermissions
    val scope = rememberCoroutineScope()
    var loading by remember { mutableStateOf(true) }
    var server by remember { mutableStateOf("") }
    var transferEndpoint by remember { mutableStateOf("") }
    var transferMethod by remember { mutableStateOf("POST") }
    var transferTemplate by remember { mutableStateOf("") }
    var useBulk by remember { mutableStateOf(false) }
    var bulkWrap by remember { mutableStateOf("") }
    var loginUser by remember { mutableStateOf("") }
    var loginPass by remember { mutableStateOf("") }
    var hasConfig by remember { mutableStateOf(false) }
    var error by remember { mutableStateOf<String?>(null) }
    var busy by remember { mutableStateOf(false) }

    fun applyFromApi(env: MemberTransferConfigEnvelope?) {
        val cfg = env?.config
        if (cfg != null) {
            hasConfig = true
            server = cfg.server.orEmpty()
            transferEndpoint = cfg.transferEndpoint.orEmpty()
            transferMethod = cfg.transferMethod ?: "POST"
            transferTemplate = cfg.transferTemplate.orEmpty()
            useBulk = cfg.useBulkMode == true
            bulkWrap = cfg.bulkWrapperTemplate.orEmpty()
            loginUser = cfg.loginCredentials?.username.orEmpty()
            loginPass = ""
        } else {
            hasConfig = false
            server = ""
            transferEndpoint = ""
            transferMethod = "POST"
            transferTemplate = ""
            useBulk = false
            bulkWrap = ""
            loginUser = ""
            loginPass = ""
        }
    }

    LaunchedEffect(clubId) {
        loading = true
        error = null
        val env = runCatching { dependencies.memberTransferConfigApi.get(clubId) }.getOrNull()
        if (env != null && !env.success) {
            applyFromApi(null)
        } else {
            applyFromApi(env)
        }
        loading = false
    }

    Column(
        modifier = Modifier
            .fillMaxSize()
            .verticalScroll(rememberScrollState())
            .padding(StammdatenPad),
    ) {
        StammdatenTopBar(tr("mobile.memberTransfer", "Mitgliedstransfer"), onBack)
        if (perms?.canReadMembers() != true) {
            Text(tr("mobile.noAccess", "Keine Berechtigung."))
            return@Column
        }
        if (loading) {
            CircularProgressIndicator(modifier = Modifier.padding(top = 24.dp))
            return@Column
        }
        Text(
            if (hasConfig) tr("mobile.memberTransferConfigured", "Konfiguration vorhanden") else tr("mobile.memberTransferNotConfigured", "Nicht konfiguriert"),
            fontWeight = FontWeight.Medium,
            modifier = Modifier.padding(top = 8.dp),
        )
        error?.let { Text(it, color = MaterialTheme.colors.error, modifier = Modifier.padding(top = 8.dp)) }

        if (perms.canWriteMembers()) {
            OutlinedTextField(
                value = server,
                onValueChange = { server = it },
                label = { Text("Server-URL") },
                modifier = Modifier.fillMaxWidth().padding(top = 8.dp),
                singleLine = true,
            )
            OutlinedTextField(
                value = transferEndpoint,
                onValueChange = { transferEndpoint = it },
                label = { Text("Transfer-Endpoint") },
                modifier = Modifier.fillMaxWidth().padding(top = 8.dp),
                singleLine = true,
            )
            OutlinedTextField(
                value = transferMethod,
                onValueChange = { transferMethod = it },
                label = { Text("HTTP-Methode") },
                modifier = Modifier.fillMaxWidth().padding(top = 8.dp),
                singleLine = true,
            )
            OutlinedTextField(
                value = transferTemplate,
                onValueChange = { transferTemplate = it },
                label = { Text("Transfer-Template") },
                modifier = Modifier.fillMaxWidth().padding(top = 8.dp),
                minLines = 4,
            )
            RowSwitch("Bulk-Modus", useBulk) { useBulk = it }
            if (useBulk) {
                OutlinedTextField(
                    value = bulkWrap,
                    onValueChange = { bulkWrap = it },
                    label = { Text("Bulk-Wrapper") },
                    modifier = Modifier.fillMaxWidth().padding(top = 8.dp),
                    minLines = 2,
                )
            }
            OutlinedTextField(
                value = loginUser,
                onValueChange = { loginUser = it },
                label = { Text("Login Benutzername") },
                modifier = Modifier.fillMaxWidth().padding(top = 8.dp),
                singleLine = true,
            )
            OutlinedTextField(
                value = loginPass,
                onValueChange = { loginPass = it },
                label = { Text("Login Passwort (nur bei Änderung)") },
                modifier = Modifier.fillMaxWidth().padding(top = 8.dp),
                singleLine = true,
            )

            Row(
                modifier = Modifier.fillMaxWidth().padding(top = 16.dp),
                horizontalArrangement = Arrangement.spacedBy(8.dp),
            ) {
                Button(
                    onClick = {
                        scope.launch {
                            busy = true
                            error = null
                            val cred = if (loginUser.isNotBlank() || loginPass.isNotBlank()) {
                                buildJsonObject {
                                    if (loginUser.isNotBlank()) put("username", JsonPrimitive(loginUser))
                                    if (loginPass.isNotBlank()) put("password", JsonPrimitive(loginPass))
                                }
                            } else {
                                null
                            }
                            runCatching {
                                val body = MemberTransferConfigSaveBody(
                                    server = server.trim(),
                                    loginEndpoint = null,
                                    transferEndpoint = transferEndpoint.trim(),
                                    transferMethod = transferMethod.trim().ifBlank { "POST" },
                                    transferTemplate = transferTemplate,
                                    useBulkMode = useBulk,
                                    bulkWrapperTemplate = bulkWrap.ifBlank { null },
                                    loginCredentials = cred,
                                )
                                val r = dependencies.memberTransferConfigApi.save(clubId, body)
                                if (!r.success) error = r.error ?: r.message ?: "Fehler"
                                else {
                                    loginPass = ""
                                    applyFromApi(r)
                                }
                            }.onFailure { error = it.message }
                            busy = false
                        }
                    },
                    enabled = !busy && server.isNotBlank() && transferEndpoint.isNotBlank() && transferTemplate.isNotBlank(),
                    modifier = Modifier.weight(1f).heightIn(min = StammdatenTouchMin),
                ) { Text(tr("common.save", "Speichern")) }
                if (hasConfig) {
                    OutlinedButton(
                        onClick = {
                            scope.launch {
                                busy = true
                                error = null
                                runCatching {
                                    val r = dependencies.memberTransferConfigApi.delete(clubId)
                                    if (r.success) applyFromApi(null)
                                    else error = r.error ?: r.message
                                }.onFailure { error = it.message }
                                busy = false
                            }
                        },
                        enabled = !busy,
                        modifier = Modifier.heightIn(min = StammdatenTouchMin),
                    ) { Text(tr("common.delete", "Löschen")) }
                }
            }
        }
    }
}

@Composable
private fun RowSwitch(label: String, checked: Boolean, onChecked: (Boolean) -> Unit) {
    Row(
        modifier = Modifier
            .fillMaxWidth()
            .padding(vertical = 4.dp),
        verticalAlignment = Alignment.CenterVertically,
        horizontalArrangement = Arrangement.SpaceBetween,
    ) {
        Text(label, modifier = Modifier.weight(1f))
        Switch(checked = checked, onCheckedChange = onChecked)
    }
}
