package com.anypreta.bountyboard.ui.admin

import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
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.padding
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.outlined.FilterList
import androidx.compose.material.icons.outlined.Group
import androidx.compose.material.icons.outlined.Search
import androidx.compose.material3.AlertDialog
import androidx.compose.material3.DropdownMenu
import androidx.compose.material3.DropdownMenuItem
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Switch
import androidx.compose.material3.SwitchDefaults
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
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.unit.dp
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import androidx.lifecycle.viewmodel.compose.viewModel
import com.anypreta.bountyboard.data.AppContainer
import com.anypreta.bountyboard.data.model.User
import com.anypreta.bountyboard.di.LocalAppContainer
import com.anypreta.bountyboard.di.containerVMFactory
import com.anypreta.bountyboard.ui.components.BBAvatar
import com.anypreta.bountyboard.ui.components.BBBadge
import com.anypreta.bountyboard.ui.components.BBButton
import com.anypreta.bountyboard.ui.components.BBButtonStyle
import com.anypreta.bountyboard.ui.components.BBCard
import com.anypreta.bountyboard.ui.components.BBTextField
import com.anypreta.bountyboard.ui.components.ConfirmDialog
import com.anypreta.bountyboard.ui.components.EmptyState
import com.anypreta.bountyboard.ui.components.FilterPill
import com.anypreta.bountyboard.ui.components.Hairline
import com.anypreta.bountyboard.ui.components.MessageBox
import com.anypreta.bountyboard.ui.components.MessageKind
import com.anypreta.bountyboard.ui.components.ScreenState
import com.anypreta.bountyboard.ui.theme.BB
import kotlinx.coroutines.launch

class AdminUsersViewModel(private val container: AppContainer) : ViewModel() {

    var loading by mutableStateOf(true)
        private set
    var error by mutableStateOf<String?>(null)
        private set
    var users by mutableStateOf<List<User>>(emptyList())
        private set
    var actionError by mutableStateOf<String?>(null)
        private set

    var query by mutableStateOf("")
    var role by mutableStateOf<String?>(null)
        private set

    init {
        load()
    }

    fun applyRole(r: String?) {
        role = r; load()
    }

    fun load() {
        loading = true; error = null
        viewModelScope.launch {
            try {
                val r = container.repo.call { adminUsers(q = query.ifBlank { null }, role = role) }
                users = r.users
            } catch (e: Exception) {
                error = e.message
            } finally {
                loading = false
            }
        }
    }

    fun save(
        id: String,
        name: String,
        admin: Boolean,
        consultant: Boolean,
        developer: Boolean,
        disabled: Boolean,
        forcePasswordReset: Boolean,
        onDone: () -> Unit,
    ) {
        actionError = null
        viewModelScope.launch {
            try {
                val body = container.gson.toJsonTree(
                    mapOf(
                        "name" to name,
                        "roles" to mapOf(
                            "admin" to admin,
                            "consultant" to consultant,
                            "developer" to developer,
                        ),
                        "disabled" to disabled,
                        "forcePasswordReset" to forcePasswordReset,
                    ),
                ).asJsonObject
                container.repo.call { adminPatchUser(id, body) }
                load()
                onDone()
            } catch (e: Exception) {
                actionError = e.message
            }
        }
    }

    fun delete(id: String, onDone: () -> Unit) {
        actionError = null
        viewModelScope.launch {
            try {
                container.repo.action { adminDeleteUser(id) }
                load()
                onDone()
            } catch (e: Exception) {
                actionError = e.message
            }
        }
    }
}

@Composable
fun AdminUsersScreen(onOpenProfile: (String) -> Unit) {
    val container = LocalAppContainer.current
    val vm: AdminUsersViewModel = viewModel(factory = containerVMFactory(container) { AdminUsersViewModel(it) })
    val p = BB.colors

    var roleMenu by remember { mutableStateOf(false) }
    var editUser by remember { mutableStateOf<User?>(null) }

    Column(Modifier.fillMaxWidth()) {
        Column(Modifier.padding(horizontal = 16.dp, vertical = 12.dp), verticalArrangement = Arrangement.spacedBy(10.dp)) {
            BBTextField(
                value = vm.query,
                onValueChange = { vm.query = it },
                label = "Search users",
                placeholder = "Name or email…",
                leadingIcon = Icons.Outlined.Search,
            )
            Row(verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.spacedBy(8.dp)) {
                Box {
                    FilterPill(
                        text = vm.role?.replaceFirstChar { it.uppercase() } ?: "All roles",
                        icon = Icons.Outlined.FilterList,
                        onClick = { roleMenu = true },
                    )
                    DropdownMenu(expanded = roleMenu, onDismissRequest = { roleMenu = false }) {
                        DropdownMenuItem(text = { Text("All roles") }, onClick = { vm.applyRole(null); roleMenu = false })
                        listOf("admin", "consultant", "developer").forEach { r ->
                            DropdownMenuItem(
                                text = { Text(r.replaceFirstChar { it.uppercase() }) },
                                onClick = { vm.applyRole(r); roleMenu = false },
                            )
                        }
                    }
                }
                BBButton("Search", onClick = { vm.load() }, style = BBButtonStyle.Primary, small = true)
            }
        }

        vm.actionError?.let {
            Box(Modifier.padding(horizontal = 16.dp)) { MessageBox(it, MessageKind.Error) }
        }

        ScreenState(loading = vm.loading, error = vm.error, onRetry = { vm.load() }) {
            if (vm.users.isEmpty()) {
                EmptyState(
                    title = "No users found",
                    subtitle = "Adjust your search or role filter.",
                    icon = Icons.Outlined.Group,
                )
            } else {
                LazyColumn(
                    contentPadding = PaddingValues(16.dp),
                    verticalArrangement = Arrangement.spacedBy(12.dp),
                ) {
                    items(vm.users, key = { it.id }) { user ->
                        UserRow(user = user, onEdit = { editUser = user })
                    }
                }
            }
        }
    }

    editUser?.let { user ->
        EditUserDialog(
            user = user,
            onSave = { name, a, c, d, disabled, force ->
                vm.save(user.id, name, a, c, d, disabled, force) { editUser = null }
            },
            onDelete = { vm.delete(user.id) { editUser = null } },
            onViewProfile = { onOpenProfile(user.id); editUser = null },
            onDismiss = { editUser = null },
        )
    }
}

@Composable
private fun UserRow(user: User, onEdit: () -> Unit) {
    val p = BB.colors
    BBCard(modifier = Modifier.fillMaxWidth()) {
        Row(Modifier.fillMaxWidth(), verticalAlignment = Alignment.CenterVertically, horizontalArrangement = Arrangement.spacedBy(12.dp)) {
            BBAvatar(user.name.ifBlank { user.email }, user.avatarFileId, size = 40.dp)
            Column(Modifier.weight(1f), verticalArrangement = Arrangement.spacedBy(4.dp)) {
                Text(user.name.ifBlank { "(no name)" }, style = MaterialTheme.typography.titleMedium, color = p.text, maxLines = 1)
                Text(user.email, style = MaterialTheme.typography.bodySmall, color = p.muted, maxLines = 1)
                Row(horizontalArrangement = Arrangement.spacedBy(6.dp), verticalAlignment = Alignment.CenterVertically) {
                    if (user.roles.admin) BBBadge("Admin", color = p.accent)
                    if (user.roles.consultant) BBBadge("Consultant", color = p.muted)
                    if (user.roles.developer) BBBadge("Developer", color = p.muted)
                    if (user.disabled) BBBadge("Disabled", color = p.err)
                }
            }
            BBButton("Edit", onClick = onEdit, style = BBButtonStyle.Default, small = true)
        }
    }
}

@Composable
private fun EditUserDialog(
    user: User,
    onSave: (String, Boolean, Boolean, Boolean, Boolean, Boolean) -> Unit,
    onDelete: () -> Unit,
    onViewProfile: () -> Unit,
    onDismiss: () -> Unit,
) {
    val p = BB.colors
    var name by remember { mutableStateOf(user.name) }
    var admin by remember { mutableStateOf(user.roles.admin) }
    var consultant by remember { mutableStateOf(user.roles.consultant) }
    var developer by remember { mutableStateOf(user.roles.developer) }
    var disabled by remember { mutableStateOf(user.disabled) }
    var force by remember { mutableStateOf(false) }
    var confirmDelete by remember { mutableStateOf(false) }

    AlertDialog(
        onDismissRequest = onDismiss,
        containerColor = p.surface,
        titleContentColor = p.text,
        textContentColor = p.muted,
        title = { Text("Edit user", style = MaterialTheme.typography.headlineSmall, color = p.text) },
        text = {
            Column(verticalArrangement = Arrangement.spacedBy(12.dp)) {
                BBTextField(value = name, onValueChange = { name = it }, label = "Name", modifier = Modifier.fillMaxWidth())
                Hairline()
                SwitchRow("Admin", admin) { admin = it }
                SwitchRow("Consultant", consultant) { consultant = it }
                SwitchRow("Developer", developer) { developer = it }
                Hairline()
                SwitchRow("Disabled", disabled) { disabled = it }
                SwitchRow("Force password reset", force) { force = it }
                Spacer(Modifier.height(2.dp))
                BBButton("View profile", onClick = onViewProfile, style = BBButtonStyle.Ghost, small = true)
                BBButton("Delete user", onClick = { confirmDelete = true }, style = BBButtonStyle.Danger, small = true)
            }
        },
        confirmButton = {
            BBButton(
                "Save",
                onClick = { onSave(name.trim(), admin, consultant, developer, disabled, force) },
                style = BBButtonStyle.Primary,
                small = true,
            )
        },
        dismissButton = { BBButton("Cancel", onClick = onDismiss, style = BBButtonStyle.Ghost, small = true) },
    )

    if (confirmDelete) {
        ConfirmDialog(
            title = "Delete user",
            message = "Permanently delete ${user.name.ifBlank { user.email }}? This cannot be undone.",
            confirmText = "Delete",
            danger = true,
            onConfirm = { confirmDelete = false; onDelete() },
            onDismiss = { confirmDelete = false },
        )
    }
}

@Composable
private fun SwitchRow(label: String, checked: Boolean, onChange: (Boolean) -> Unit) {
    val p = BB.colors
    Row(
        Modifier.fillMaxWidth(),
        verticalAlignment = Alignment.CenterVertically,
        horizontalArrangement = Arrangement.SpaceBetween,
    ) {
        Text(label, style = MaterialTheme.typography.bodyLarge, color = p.text, modifier = Modifier.weight(1f))
        Switch(
            checked = checked,
            onCheckedChange = onChange,
            colors = SwitchDefaults.colors(
                checkedThumbColor = p.onAccent,
                checkedTrackColor = p.accent,
                uncheckedTrackColor = p.surface2,
                uncheckedBorderColor = p.border,
            ),
        )
    }
}
