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.mutableStateMapOf
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.RolePermissionMatrix
import de.tsschulz.tt_tagebuch.shared.api.models.ApiLogDetailDto
import de.tsschulz.tt_tagebuch.shared.api.models.ClubPermissionMemberDto
import de.tsschulz.tt_tagebuch.shared.api.models.PermissionResourceDto
import de.tsschulz.tt_tagebuch.shared.api.models.canReadApprovals
import de.tsschulz.tt_tagebuch.shared.api.models.canReadClubPermissions
import de.tsschulz.tt_tagebuch.shared.api.models.canWriteApprovals
import de.tsschulz.tt_tagebuch.shared.api.models.canWriteClubPermissions
import de.tsschulz.tt_tagebuch.shared.i18n.MobileStrings
import kotlinx.coroutines.launch
import kotlinx.serialization.json.JsonNull
import kotlinx.serialization.json.JsonObject
import kotlinx.serialization.json.JsonPrimitive
import kotlinx.serialization.json.booleanOrNull
import kotlinx.serialization.json.buildJsonObject

private val ClubAdminPad = 20.dp
private val ClubAdminTouchMin = 48.dp

internal enum class ClubAdminSettingsSection {
    Pending,
    Permissions,
    Logs,
}

@Composable
internal fun ClubAdminFlowScreen(
    destination: ClubAdminSettingsSection,
    dependencies: AppDependencies,
    onBack: () -> Unit,
) {
    BackHandler(onBack = onBack)
    when (destination) {
        ClubAdminSettingsSection.Pending ->
            ClubAdminPendingScreen(dependencies = dependencies, onBack = onBack)
        ClubAdminSettingsSection.Permissions ->
            ClubAdminPermissionsScreen(dependencies = dependencies, onBack = onBack)
        ClubAdminSettingsSection.Logs ->
            ClubAdminLogsScreen(dependencies = dependencies, onBack = onBack)
    }
}

@Composable
private fun ClubAdminTopBar(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))
}

private fun readTri(root: JsonObject?, resource: String, action: String): Boolean? {
    val mod = root?.get(resource) ?: return null
    val obj = mod as? JsonObject ?: return null
    if (!obj.containsKey(action)) return null
    val el = obj[action] ?: return null
    if (el is JsonNull) return null
    return (el as? JsonPrimitive)?.booleanOrNull
}

private fun overridesToJson(
    structure: Map<String, PermissionResourceDto>,
    overrides: Map<String, Boolean?>,
): JsonObject = buildJsonObject {
    structure.forEach { (res, spec) ->
        val inner = buildJsonObject {
            spec.actions.forEach { a ->
                val k = permKey(res, a)
                when (val v = overrides[k]) {
                    true -> put(a, JsonPrimitive(true))
                    false -> put(a, JsonPrimitive(false))
                    null -> {}
                }
            }
        }
        if (inner.isNotEmpty()) put(res, inner)
    }
}

private fun permKey(resource: String, action: String) = "$resource#$action"

@Composable
private fun ClubAdminPendingScreen(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 pendingState by dependencies.pendingApprovalsManager.state.collectAsState()
    val clubId = clubState.currentClubId ?: return
    val perms = clubState.currentPermissions
    val canWrite = perms?.canWriteApprovals() == true
    val scope = rememberCoroutineScope()
    var actionError by remember { mutableStateOf<String?>(null) }

    LaunchedEffect(clubId) {
        dependencies.pendingApprovalsManager.load(clubId)
    }

    Column(
        modifier = Modifier
            .fillMaxSize()
            .padding(horizontal = ClubAdminPad, vertical = 16.dp),
    ) {
        ClubAdminTopBar(tr("mobile.pendingApprovals", "Ausstehende Freigaben"), onBack)
        actionError?.let {
            Text(it, color = MaterialTheme.colors.error, modifier = Modifier.padding(bottom = 8.dp))
        }
        if (perms != null && !perms.canReadApprovals()) {
            Text(tr("mobile.noAccess", "Keine Berechtigung."), modifier = Modifier.padding(top = 8.dp))
            return
        }
        if (pendingState.isLoading && pendingState.pending.isEmpty()) {
            CircularProgressIndicator(modifier = Modifier.padding(top = 24.dp))
            return
        }
        pendingState.error?.let { Text(it, color = MaterialTheme.colors.error) }
        if (pendingState.pending.isEmpty()) {
            Text(tr("mobile.pendingEmpty", "Keine ausstehenden Anträge."), modifier = Modifier.padding(top = 16.dp))
        } else {
            LazyColumn(verticalArrangement = Arrangement.spacedBy(8.dp)) {
                items(pendingState.pending, key = { it.userId }) { row ->
                    val u = row.user
                    val label = listOfNotNull(u?.firstName, u?.lastName).joinToString(" ").trim()
                        .ifEmpty { u?.email ?: "User ${row.userId}" }
                    Card(modifier = Modifier.fillMaxWidth(), elevation = 1.dp) {
                        Column(modifier = Modifier.padding(12.dp)) {
                            Text(label, fontWeight = FontWeight.SemiBold)
                            u?.email?.let { Text(it, style = MaterialTheme.typography.caption) }
                            Row(
                                modifier = Modifier
                                    .fillMaxWidth()
                                    .padding(top = 8.dp),
                                horizontalArrangement = Arrangement.spacedBy(8.dp),
                            ) {
                                Button(
                                    onClick = {
                                        actionError = null
                                        scope.launch {
                                            try {
                                                dependencies.pendingApprovalsManager.approve(clubId, row.userId)
                                            } catch (t: Throwable) {
                                                actionError = t.message
                                            }
                                        }
                                    },
                                    enabled = canWrite,
                                    modifier = Modifier.weight(1f).heightIn(min = ClubAdminTouchMin),
                                ) { Text(tr("mobile.approve", "Freigeben")) }
                                OutlinedButton(
                                    onClick = {
                                        actionError = null
                                        scope.launch {
                                            try {
                                                dependencies.pendingApprovalsManager.reject(clubId, row.userId)
                                            } catch (t: Throwable) {
                                                actionError = t.message
                                            }
                                        }
                                    },
                                    enabled = canWrite,
                                    modifier = Modifier.weight(1f).heightIn(min = ClubAdminTouchMin),
                                ) { Text(tr("mobile.reject", "Ablehnen")) }
                            }
                        }
                    }
                }
            }
        }
    }
}

@Composable
private fun ClubAdminPermissionsScreen(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 adminState by dependencies.permissionsAdminManager.state.collectAsState()
    val clubId = clubState.currentClubId ?: return
    val perms = clubState.currentPermissions
    val canWrite = perms?.canWriteClubPermissions() == true
    val scope = rememberCoroutineScope()
    var roleMenuFor by remember { mutableStateOf<Int?>(null) }
    var customizeFor by remember { mutableStateOf<ClubPermissionMemberDto?>(null) }
    val overrides = remember { mutableStateMapOf<String, Boolean?>() }
    var customizeSaving by remember { mutableStateOf(false) }
    var opError by remember { mutableStateOf<String?>(null) }

    LaunchedEffect(clubId) {
        dependencies.permissionsAdminManager.load(clubId)
    }

    LaunchedEffect(customizeFor, adminState.permissionStructure) {
        val m = customizeFor ?: return@LaunchedEffect
        if (adminState.permissionStructure.isEmpty()) return@LaunchedEffect
        overrides.clear()
        adminState.permissionStructure.forEach { (res, spec) ->
            spec.actions.forEach { a ->
                overrides[permKey(res, a)] = readTri(m.permissions, res, a)
            }
        }
    }

    Column(
        modifier = Modifier
            .fillMaxSize()
            .padding(horizontal = ClubAdminPad, vertical = 16.dp),
    ) {
        ClubAdminTopBar(tr("mobile.permissionsAdmin", "Berechtigungen"), onBack)
        opError?.let { Text(it, color = MaterialTheme.colors.error, modifier = Modifier.padding(bottom = 8.dp)) }
        if (perms != null && !perms.canReadClubPermissions()) {
            Text(tr("mobile.noAccess", "Keine Berechtigung."))
            return
        }
        if (adminState.isLoading && adminState.members.isEmpty()) {
            CircularProgressIndicator(modifier = Modifier.padding(top = 24.dp))
            return
        }
        adminState.error?.let { Text(it, color = MaterialTheme.colors.error) }
        LazyColumn(verticalArrangement = Arrangement.spacedBy(8.dp)) {
            items(adminState.members, key = { it.userId }) { m ->
                val email = m.user?.email ?: "User ${m.userId}"
                Card(modifier = Modifier.fillMaxWidth(), elevation = 1.dp) {
                    Column(modifier = Modifier.padding(12.dp)) {
                        Text(email, fontWeight = FontWeight.SemiBold)
                        if (m.isOwner) {
                            Text(tr("mobile.clubOwner", "Vereinsbesitzer"), style = MaterialTheme.typography.caption)
                        }
                        Row(
                            modifier = Modifier.fillMaxWidth().padding(top = 8.dp),
                            verticalAlignment = Alignment.CenterVertically,
                            horizontalArrangement = Arrangement.SpaceBetween,
                        ) {
                            Text(tr("mobile.role", "Rolle"))
                            Box {
                                TextButton(
                                    enabled = canWrite && !m.isOwner,
                                    onClick = { roleMenuFor = m.userId },
                                ) {
                                    Text(adminState.availableRoles.firstOrNull { it.value == m.role }?.label ?: m.role)
                                }
                                DropdownMenu(
                                    expanded = roleMenuFor == m.userId,
                                    onDismissRequest = { roleMenuFor = null },
                                ) {
                                    adminState.availableRoles.forEach { role ->
                                        DropdownMenuItem(
                                            onClick = {
                                                roleMenuFor = null
                                                opError = null
                                                scope.launch {
                                                    try {
                                                        dependencies.permissionsAdminManager.updateRole(clubId, m.userId, role.value)
                                                    } catch (t: Throwable) {
                                                        opError = t.message
                                                    }
                                                }
                                            },
                                        ) { Text(role.label) }
                                    }
                                }
                            }
                        }
                        Row(
                            modifier = Modifier.fillMaxWidth(),
                            verticalAlignment = Alignment.CenterVertically,
                            horizontalArrangement = Arrangement.SpaceBetween,
                        ) {
                            Text(tr("mobile.memberApproved", "Aktiv"))
                            Switch(
                                checked = m.approved != false,
                                enabled = canWrite && !m.isOwner,
                                onCheckedChange = { on ->
                                    opError = null
                                    scope.launch {
                                        try {
                                            dependencies.permissionsAdminManager.updateApproved(clubId, m.userId, on)
                                        } catch (t: Throwable) {
                                            opError = t.message
                                        }
                                    }
                                },
                            )
                        }
                        TextButton(
                            enabled = canWrite && !m.isOwner,
                            onClick = { customizeFor = m },
                            modifier = Modifier.fillMaxWidth().heightIn(min = ClubAdminTouchMin),
                        ) { Text(tr("mobile.customizePermissions", "Berechtigungen anpassen")) }
                    }
                }
            }
        }
    }

    val dialogMember = customizeFor
    if (dialogMember != null) {
        StableAlertDialog(
            onDismissRequest = { if (!customizeSaving) customizeFor = null },
            title = { Text(dialogMember.user?.email ?: "User ${dialogMember.userId}") },
            text = {
                Column(
                    modifier = Modifier
                        .verticalScroll(rememberScrollState())
                        .heightIn(max = 420.dp),
                ) {
                    adminState.permissionStructure.forEach { (res, spec) ->
                        Text(
                            spec.label.ifEmpty { res },
                            fontWeight = FontWeight.SemiBold,
                            modifier = Modifier.padding(top = 8.dp, bottom = 4.dp),
                        )
                        spec.actions.forEach { action ->
                            val k = permKey(res, action)
                            val tri = overrides[k]
                            val inherited = RolePermissionMatrix.defaultAction(dialogMember.role, res, action)
                            val label = when (tri) {
                                null -> tr("mobile.permInherit", "Standard") + " (${if (inherited) tr("mobile.yes", "Ja") else tr("mobile.no", "Nein")})"
                                true -> tr("mobile.permAllow", "Erlaubt")
                                false -> tr("mobile.permDeny", "Verweigert")
                            }
                            TextButton(
                                onClick = {
                                    overrides[k] = when (tri) {
                                        null -> true
                                        true -> false
                                        false -> null
                                    }
                                },
                                modifier = Modifier.fillMaxWidth(),
                            ) {
                                Column(modifier = Modifier.fillMaxWidth()) {
                                    Text(action, style = MaterialTheme.typography.caption)
                                    Text(label)
                                }
                            }
                            Divider()
                        }
                    }
                }
            },
            confirmButton = {
                TextButton(
                    enabled = !customizeSaving,
                    onClick = {
                        scope.launch {
                            customizeSaving = true
                            opError = null
                            try {
                                val json = overridesToJson(adminState.permissionStructure, overrides)
                                dependencies.permissionsAdminManager.saveCustomPermissions(
                                    clubId,
                                    dialogMember.userId,
                                    json,
                                )
                                customizeFor = null
                            } catch (t: Throwable) {
                                opError = t.message
                            } finally {
                                customizeSaving = false
                            }
                        }
                    },
                ) { Text(tr("common.save", "Speichern")) }
            },
            dismissButton = {
                TextButton(enabled = !customizeSaving, onClick = { customizeFor = null }) {
                    Text(tr("common.cancel", "Abbrechen"))
                }
            },
        )
    }
}

@Composable
private fun ClubAdminLogsScreen(dependencies: AppDependencies, onBack: () -> Unit) {
    val languageCode = LocalLanguageCode.current
    fun tr(key: String, fb: String) = MobileStrings.get(languageCode, key, fb)
    val logsState by dependencies.apiLogsManager.state.collectAsState()
    val scope = rememberCoroutineScope()
    var pathFilter by remember { mutableStateOf("") }
    var detailId by remember { mutableStateOf<Int?>(null) }
    var detail by remember { mutableStateOf<ApiLogDetailDto?>(null) }
    var detailLoading by remember { mutableStateOf(false) }

    LaunchedEffect(Unit) {
        dependencies.apiLogsManager.load(resetOffset = true)
    }

    Column(
        modifier = Modifier
            .fillMaxSize()
            .padding(horizontal = ClubAdminPad, vertical = 16.dp),
    ) {
        ClubAdminTopBar(tr("mobile.apiLogs", "API-Logs"), onBack)
        Row(
            modifier = Modifier.fillMaxWidth(),
            horizontalArrangement = Arrangement.spacedBy(8.dp),
            verticalAlignment = Alignment.CenterVertically,
        ) {
            OutlinedTextField(
                value = pathFilter,
                onValueChange = { pathFilter = it },
                label = { Text(tr("mobile.logPathFilter", "Pfad enthält")) },
                singleLine = true,
                modifier = Modifier.weight(1f),
            )
            Button(
                onClick = {
                    scope.launch {
                        dependencies.apiLogsManager.load(
                            pathContains = pathFilter.takeIf { it.isNotBlank() },
                            resetOffset = true,
                        )
                    }
                },
                modifier = Modifier.heightIn(min = ClubAdminTouchMin),
            ) { Text(tr("mobile.apply", "Anwenden")) }
        }
        logsState.error?.let { Text(it, color = MaterialTheme.colors.error, modifier = Modifier.padding(top = 8.dp)) }
        Row(
            modifier = Modifier
                .fillMaxWidth()
                .padding(top = 8.dp),
            horizontalArrangement = Arrangement.SpaceBetween,
            verticalAlignment = Alignment.CenterVertically,
        ) {
            OutlinedButton(
                enabled = !logsState.isLoading && logsState.offset > 0,
                onClick = {
                    scope.launch {
                        dependencies.apiLogsManager.previousPage(pathContains = pathFilter.takeIf { it.isNotBlank() })
                    }
                },
                modifier = Modifier.heightIn(min = ClubAdminTouchMin),
            ) { Text(tr("mobile.prevPage", "Zurück")) }
            Text(
                "${logsState.offset + 1}–${(logsState.offset + logsState.logs.size).coerceAtLeast(logsState.offset)} / ${logsState.total}",
                style = MaterialTheme.typography.caption,
            )
            OutlinedButton(
                enabled = !logsState.isLoading && logsState.offset + logsState.logs.size < logsState.total,
                onClick = {
                    scope.launch {
                        dependencies.apiLogsManager.nextPage(pathContains = pathFilter.takeIf { it.isNotBlank() })
                    }
                },
                modifier = Modifier.heightIn(min = ClubAdminTouchMin),
            ) { Text(tr("mobile.nextPage", "Weiter")) }
        }
        if (logsState.isLoading && logsState.logs.isEmpty()) {
            CircularProgressIndicator(modifier = Modifier.padding(top = 24.dp))
        } else {
            LazyColumn(modifier = Modifier.padding(top = 8.dp), verticalArrangement = Arrangement.spacedBy(4.dp)) {
                items(logsState.logs, key = { it.id }) { row ->
                    Card(
                        modifier = Modifier
                            .fillMaxWidth()
                            .padding(vertical = 2.dp),
                        elevation = 1.dp,
                    ) {
                        TextButton(
                            onClick = {
                                scope.launch {
                                    detailId = row.id
                                    detail = null
                                    detailLoading = true
                                    detail = dependencies.apiLogsManager.fetchDetail(row.id)
                                    detailLoading = false
                                }
                            },
                            modifier = Modifier.fillMaxWidth(),
                        ) {
                            Column(modifier = Modifier.fillMaxWidth().padding(4.dp)) {
                                Text(
                                    "${row.method ?: "?"} ${row.statusCode ?: "-"}",
                                    fontWeight = FontWeight.SemiBold,
                                )
                                Text(row.path ?: "-", style = MaterialTheme.typography.caption)
                                row.createdAt?.let { Text(it, style = MaterialTheme.typography.caption) }
                            }
                        }
                    }
                }
            }
        }
    }

    if (detailId != null) {
        StableAlertDialog(
            onDismissRequest = { detailId = null },
            title = { Text(tr("mobile.logDetail", "Log-Detail")) },
            text = {
                when {
                    detailLoading -> CircularProgressIndicator()
                    detail != null -> {
                        val d = detail!!
                        Column(verticalArrangement = Arrangement.spacedBy(4.dp)) {
                            Text("id=${d.id}")
                            d.method?.let { Text("method=$it") }
                            d.path?.let { Text("path=$it") }
                            d.statusCode?.let { Text("status=$it") }
                            d.executionTime?.let { Text("ms=$it") }
                            d.createdAt?.let { Text(it) }
                            d.errorMessage?.takeIf { it.isNotBlank() }?.let { Text(it, color = MaterialTheme.colors.error) }
                            d.ipAddress?.let { Text("ip=$it") }
                            d.userAgent?.let { Text(it, style = MaterialTheme.typography.caption) }
                        }
                    }
                    else -> Text(tr("mobile.logDetailFailed", "Konnte nicht geladen werden."))
                }
            },
            confirmButton = {
                TextButton(onClick = { detailId = null }) { Text(tr("common.close", "Schließen")) }
            },
        )
    }
}
