package de.tsschulz.tt_tagebuch.app.ui

import androidx.activity.compose.BackHandler
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.PickVisualMediaRequest
import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
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.imePadding
import androidx.compose.foundation.layout.navigationBarsPadding
import androidx.compose.foundation.layout.padding
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.MaterialTheme
import androidx.compose.material.OutlinedButton
import androidx.compose.material.OutlinedTextField
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.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.input.PasswordVisualTransformation
import androidx.compose.ui.unit.dp
import de.tsschulz.tt_tagebuch.app.AppDependencies
import de.tsschulz.tt_tagebuch.shared.api.models.MemberGroupPhotoDto
import de.tsschulz.tt_tagebuch.shared.api.models.MemberTransferConfigEnvelope
import de.tsschulz.tt_tagebuch.shared.api.models.MemberTransferRunBody
import de.tsschulz.tt_tagebuch.shared.api.toAbsoluteUrl
import de.tsschulz.tt_tagebuch.shared.i18n.MobileStrings
import kotlinx.coroutines.launch
import kotlinx.serialization.json.JsonPrimitive
import kotlinx.serialization.json.booleanOrNull
import kotlinx.serialization.json.contentOrNull
import kotlinx.serialization.json.intOrNull
import kotlinx.serialization.json.jsonPrimitive
import kotlinx.serialization.json.buildJsonObject

private val MembersExtraHorizontalPadding = 20.dp
private val MembersExtraTouchMin = 48.dp

@Composable
fun MemberGroupPhotoManageRoute(
    clubId: Int,
    dependencies: AppDependencies,
    canReadMembers: Boolean,
    canWriteMembers: Boolean,
    onBack: () -> Unit,
    onOpenPortraitCrop: () -> Unit = {},
) {
    val languageCode = LocalLanguageCode.current
    fun s(key: String, fb: String) = MobileStrings.get(languageCode, key, fb)
    BackHandler(onBack = onBack)
    val androidContext = LocalContext.current
    var groupPhotos by remember { mutableStateOf<List<MemberGroupPhotoDto>>(emptyList()) }
    var groupPhotoBusy by remember { mutableStateOf(false) }
    var newGroupPhotoTitle by rememberSaveable { mutableStateOf("") }
    var newGroupPhotoDescription by rememberSaveable { mutableStateOf("") }
    var loadError by remember { mutableStateOf<String?>(null) }

    LaunchedEffect(clubId) {
        groupPhotoBusy = true
        loadError = null
        groupPhotos = runCatching { dependencies.diaryManager.listMemberGroupPhotos(clubId) }.getOrElse {
            loadError = it.message
            emptyList()
        }
        groupPhotoBusy = false
    }

    val pickGroupPhoto = rememberLauncherForActivityResult(ActivityResultContracts.PickVisualMedia()) { uri ->
        if (uri == null || !canWriteMembers) return@rememberLauncherForActivityResult
        val title = newGroupPhotoTitle.trim().ifBlank { "Gruppenfoto" }
        dependencies.applicationScope.launch {
            groupPhotoBusy = true
            runCatching {
                val bytes = androidContext.contentResolver.openInputStream(uri)?.use { it.readBytes() } ?: return@runCatching
                dependencies.diaryManager.uploadMemberGroupPhoto(
                    clubId,
                    bytes,
                    title = title,
                    description = newGroupPhotoDescription.trim(),
                )
                newGroupPhotoTitle = ""
                newGroupPhotoDescription = ""
                groupPhotos = dependencies.diaryManager.listMemberGroupPhotos(clubId)
            }
            groupPhotoBusy = false
        }
    }

    Column(
        modifier = Modifier
            .fillMaxSize()
            .imePadding()
            .navigationBarsPadding()
            .verticalScroll(rememberScrollState())
            .padding(horizontal = MembersExtraHorizontalPadding, vertical = 16.dp),
    ) {
        Row(
            modifier = Modifier.fillMaxWidth(),
            horizontalArrangement = Arrangement.SpaceBetween,
            verticalAlignment = Alignment.CenterVertically,
        ) {
            Text(s("members.groupPhotoTitle", "Gruppenfoto"), style = MaterialTheme.typography.h6)
            TextButton(onClick = onBack) { Text(s("mobile.back", "Zurück")) }
        }
        Text(
            s(
                "members.groupPhotoMobileHint",
                "Gruppenfotos werden im Verein gespeichert (wie im Tagebuch). Einzelportraits legst du pro Mitglied unter „Profilbild“ fest.",
            ),
            style = MaterialTheme.typography.body2,
            color = MaterialTheme.colors.onSurface.copy(alpha = 0.75f),
            modifier = Modifier.padding(bottom = 12.dp),
        )
        if (canWriteMembers) {
            OutlinedButton(
                onClick = onOpenPortraitCrop,
                modifier = Modifier
                    .fillMaxWidth()
                    .padding(bottom = 12.dp)
                    .heightIn(min = MembersExtraTouchMin),
            ) {
                Text(s("members.openPortraitCrop", "Portrait aus Bild zuschneiden"))
            }
        }
        loadError?.let { Text(it, color = MaterialTheme.colors.error, modifier = Modifier.padding(bottom = 8.dp)) }
        if (!canReadMembers) {
            Text(s("members.noReadPermission", "Keine Berechtigung."))
            return@Column
        }
        if (canWriteMembers) {
            OutlinedTextField(
                value = newGroupPhotoTitle,
                onValueChange = { newGroupPhotoTitle = it },
                label = { Text(s("diary.groupPhotoTitle", "Titel")) },
                modifier = Modifier.fillMaxWidth(),
                enabled = !groupPhotoBusy,
                singleLine = true,
            )
            OutlinedButton(
                onClick = {
                    pickGroupPhoto.launch(PickVisualMediaRequest(ActivityResultContracts.PickVisualMedia.ImageOnly))
                },
                enabled = !groupPhotoBusy,
                modifier = Modifier
                    .fillMaxWidth()
                    .padding(top = 8.dp)
                    .heightIn(min = MembersExtraTouchMin),
            ) { Text(s("diary.uploadGroupPhoto", "Foto wählen")) }
            OutlinedTextField(
                value = newGroupPhotoDescription,
                onValueChange = { newGroupPhotoDescription = it },
                label = { Text(s("diary.groupPhotoDescription", "Beschreibung (optional)")) },
                modifier = Modifier.fillMaxWidth().padding(top = 8.dp),
                enabled = !groupPhotoBusy,
                singleLine = false,
                maxLines = 3,
            )
        }
        if (groupPhotoBusy) {
            CircularProgressIndicator(modifier = Modifier.padding(16.dp).align(Alignment.CenterHorizontally))
        }
        if (groupPhotos.isEmpty() && !groupPhotoBusy) {
            Text(s("diary.noGroupPhotos", "Keine Gruppenfotos."), modifier = Modifier.padding(top = 12.dp))
        } else {
            val auth = dependencies.diaryAuthHeaders()
            groupPhotos.forEach { ph ->
                val url = ph.imageUrl?.let { dependencies.apiConfig.toAbsoluteUrl(it) }
                Card(
                    modifier = Modifier
                        .fillMaxWidth()
                        .padding(vertical = 6.dp),
                    elevation = 1.dp,
                ) {
                    Column(modifier = Modifier.padding(8.dp)) {
                        Text(ph.title.orEmpty(), fontWeight = FontWeight.SemiBold)
                        if (!ph.description.isNullOrBlank()) {
                            Text(ph.description.orEmpty(), style = MaterialTheme.typography.caption)
                        }
                        if (url != null) {
                            AuthenticatedAsyncImage(
                                imageUrl = url,
                                authHeaders = auth,
                                modifier = Modifier
                                    .fillMaxWidth()
                                    .height(200.dp)
                                    .padding(top = 6.dp),
                                contentDescription = ph.title,
                            )
                        }
                        if (canWriteMembers) {
                            TextButton(
                                enabled = !groupPhotoBusy,
                                onClick = {
                                    dependencies.applicationScope.launch {
                                        groupPhotoBusy = true
                                        runCatching {
                                            dependencies.diaryManager.deleteMemberGroupPhoto(clubId, ph.id)
                                            groupPhotos = dependencies.diaryManager.listMemberGroupPhotos(clubId)
                                        }
                                        groupPhotoBusy = false
                                    }
                                },
                            ) { Text(s("common.delete", "Löschen")) }
                        }
                    }
                }
            }
        }
    }
}

@Composable
fun MemberTransferRunRoute(
    clubId: Int,
    dependencies: AppDependencies,
    canWriteMembers: Boolean,
    onBack: () -> Unit,
) {
    val languageCode = LocalLanguageCode.current
    fun s(key: String, fb: String) = MobileStrings.get(languageCode, key, fb)
    BackHandler(onBack = onBack)
    var loading by remember { mutableStateOf(true) }
    var envelope by remember { mutableStateOf<MemberTransferConfigEnvelope?>(null) }
    var transferBusy by remember { mutableStateOf(false) }
    var loginUser by rememberSaveable { mutableStateOf("") }
    var loginPass by rememberSaveable { mutableStateOf("") }
    var statusText by remember { mutableStateOf<String?>(null) }

    LaunchedEffect(clubId) {
        loading = true
        envelope = runCatching { dependencies.memberTransferConfigApi.get(clubId) }.getOrNull()
        loading = false
    }

    Column(
        modifier = Modifier
            .fillMaxSize()
            .imePadding()
            .navigationBarsPadding()
            .verticalScroll(rememberScrollState())
            .padding(horizontal = MembersExtraHorizontalPadding, vertical = 16.dp),
    ) {
        Row(
            modifier = Modifier.fillMaxWidth(),
            horizontalArrangement = Arrangement.SpaceBetween,
            verticalAlignment = Alignment.CenterVertically,
        ) {
            Text(s("members.transferMembers", "Mitgliedstransfer"), style = MaterialTheme.typography.h6)
            TextButton(onClick = onBack) { Text(s("mobile.back", "Zurück")) }
        }
        if (!canWriteMembers) {
            Text(s("members.transferNoWrite", "Keine Schreibberechtigung für Mitglieder."))
            return@Column
        }
        if (loading) {
            CircularProgressIndicator(modifier = Modifier.padding(24.dp).align(Alignment.CenterHorizontally))
            return@Column
        }
        val cfg = envelope?.config
        val hasConfig = cfg != null &&
            !cfg.transferEndpoint.isNullOrBlank() &&
            !cfg.transferTemplate.isNullOrBlank() &&
            !cfg.server.isNullOrBlank()
        if (!hasConfig) {
            Text(
                s(
                    "members.transferConfigMissing",
                    "Es ist keine Transfer-Konfiguration hinterlegt. Lege sie unter „Mehr“ → Vereinsstammdaten → Mitgliedstransfer an.",
                ),
                modifier = Modifier.padding(top = 8.dp),
            )
            return@Column
        }
        val c = cfg!!
        Text(
            s("members.transferActiveOnlyHint", "Es werden nur aktive Mitglieder übertragen (serverseitig)."),
            style = MaterialTheme.typography.caption,
            color = MaterialTheme.colors.onSurface.copy(alpha = 0.75f),
            modifier = Modifier.padding(bottom = 8.dp),
        )
        Text("${s("memberTransferDialog.server", "Server")}: ${c.server}", style = MaterialTheme.typography.body2)
        Text("${s("memberTransferDialog.endpoint", "Endpoint")}: ${c.transferEndpoint}", style = MaterialTheme.typography.body2)
        Text("${s("memberTransferDialog.method", "Methode")}: ${c.transferMethod ?: "POST"}", style = MaterialTheme.typography.body2)
        Text(
            "${s("memberTransferDialog.mode", "Modus")}: ${if (c.useBulkMode == true) s("memberTransferDialog.bulkImport", "Bulk") else s("memberTransferDialog.single", "Einzeln")}",
            style = MaterialTheme.typography.body2,
            modifier = Modifier.padding(bottom = 12.dp),
        )
        if (!c.loginEndpoint.isNullOrBlank()) {
            Text(s("memberTransferDialog.loginDataOverride", "Login (optional)"), fontWeight = FontWeight.SemiBold)
            OutlinedTextField(
                value = loginUser,
                onValueChange = { loginUser = it },
                label = { Text(s("memberTransferDialog.usernameEmail", "Benutzername / E-Mail")) },
                modifier = Modifier.fillMaxWidth().padding(top = 6.dp),
                enabled = !transferBusy,
                singleLine = true,
            )
            OutlinedTextField(
                value = loginPass,
                onValueChange = { loginPass = it },
                label = { Text(s("memberTransferDialog.passwordPlaceholder", "Passwort")) },
                modifier = Modifier.fillMaxWidth().padding(top = 6.dp),
                enabled = !transferBusy,
                singleLine = true,
                visualTransformation = PasswordVisualTransformation(),
            )
        }
        statusText?.let {
            Text(it, modifier = Modifier.padding(top = 12.dp), color = MaterialTheme.colors.primary)
        }
        Button(
            onClick = {
                dependencies.applicationScope.launch {
                    transferBusy = true
                    statusText = null
                    runCatching {
                        val creds = buildJsonObject {
                            val u = loginUser.trim()
                            val p = loginPass.trim()
                            if (u.isNotEmpty()) put("username", JsonPrimitive(u))
                            if (p.isNotEmpty()) put("password", JsonPrimitive(p))
                        }
                        val body = MemberTransferRunBody(
                            transferEndpoint = c.transferEndpoint.orEmpty(),
                            transferMethod = c.transferMethod ?: "POST",
                            transferFormat = c.transferFormat ?: "json",
                            transferTemplate = c.transferTemplate.orEmpty(),
                            useBulkMode = c.useBulkMode == true,
                            bulkWrapperTemplate = c.bulkWrapperTemplate?.takeIf { it.isNotBlank() },
                            loginEndpoint = c.loginEndpoint?.takeIf { it.isNotBlank() },
                            loginFormat = c.loginFormat?.takeIf { it.isNotBlank() },
                            loginCredentials = creds.takeIf { it.isNotEmpty() },
                        )
                        val jo = dependencies.membersManager.transferMembers(clubId, body)
                        val ok = jo["success"]?.jsonPrimitive?.booleanOrNull == true
                        if (ok) {
                            val msg = jo["message"]?.jsonPrimitive?.contentOrNull
                                ?: s("memberTransferDialog.transferSuccessShort", "Transfer abgeschlossen.")
                            val transferred = jo["transferred"]?.jsonPrimitive?.let { p ->
                                p.intOrNull?.toString() ?: p.contentOrNull
                            }
                            val total = jo["total"]?.jsonPrimitive?.let { p ->
                                p.intOrNull?.toString() ?: p.contentOrNull
                            }
                            statusText = if (transferred != null && total != null) "$msg ($transferred / $total)" else msg
                        } else {
                            val err = jo["error"]?.jsonPrimitive?.contentOrNull
                                ?: jo["message"]?.jsonPrimitive?.contentOrNull
                                ?: s("memberTransferDialog.transferFailed", "Transfer fehlgeschlagen.")
                            statusText = err
                        }
                    }.onFailure {
                        statusText = it.message ?: s("memberTransferDialog.transferError", "Netzwerkfehler.")
                    }
                    transferBusy = false
                }
            },
            enabled = !transferBusy,
            modifier = Modifier
                .fillMaxWidth()
                .padding(top = 16.dp)
                .heightIn(min = MembersExtraTouchMin),
        ) {
            Text(if (transferBusy) s("memberTransferDialog.transferring", "Übertrage…") else s("memberTransferDialog.transfer", "Transfer starten"))
        }
    }
}
