package ru.durakscore.app

import androidx.activity.compose.BackHandler
import androidx.compose.foundation.BorderStroke
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
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.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Card
import androidx.compose.material3.CardDefaults
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
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.graphics.Color
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import java.util.Date

private data class PendingAccessRequest(
    val uid: String,
    val name: String,
    val email: String,
    val createdAt: Timestamp?
)

private data class ActiveMember(
    val uid: String,
    val name: String,
    val playerId: String,
    val role: String,
    val active: Boolean
)

private data class UserSlot(
    val playerId: String,
    val name: String,
    val role: String
)

private val userSlots =
    listOf(
        UserSlot("denis", "Денис", "admin"),
        UserSlot("dmitry", "Дмитрий", "scorekeeper"),
        UserSlot("rybka", "Рыбка", "viewer"),
        UserSlot("masha", "Маша", "viewer")
    )

@Composable
fun AdminUsersScreen(
    access: UserAccess,
    onBack: () -> Unit
) {
    BackHandler(onBack = onBack)

    var requests by remember {
        mutableStateOf<List<PendingAccessRequest>>(emptyList())
    }

    var members by remember {
        mutableStateOf<List<ActiveMember>>(emptyList())
    }

    var requestsLoaded by remember {
        mutableStateOf(false)
    }

    var membersLoaded by remember {
        mutableStateOf(false)
    }

    var errorText by remember {
        mutableStateOf<String?>(null)
    }

    var actionUid by remember {
        mutableStateOf<String?>(null)
    }

    var actionError by remember {
        mutableStateOf<String?>(null)
    }

    var reloadKey by remember {
        mutableStateOf(0)
    }

    val isAdmin =
        access.role == "admin"

    LaunchedEffect(
        isAdmin,
        reloadKey
    ) {

        if (
            !isAdmin
        ) {
            requestsLoaded =
                true

            membersLoaded =
                true

            errorText =
                "Этот раздел доступен только администратору"

            return@LaunchedEffect
        }

        val user =
            DurakAuthSession.current()

        if (
            user ==
            null
        ) {
            requestsLoaded =
                true

            membersLoaded =
                true

            errorText =
                "Пользователь не авторизован"

            return@LaunchedEffect
        }

        DurakServerApi
            .loadAdminUsers(
                user =
                    user,
                onSuccess = {
                        loaded ->

                    requests =
                        loaded.requests
                            .map {
                                    request ->

                                PendingAccessRequest(
                                    uid =
                                        request.uid,
                                    name =
                                        request.name,
                                    email =
                                        request.email,
                                    createdAt =
                                        request
                                            .createdAtEpochMillis
                                            ?.let {
                                                Timestamp(
                                                    Date(
                                                        it
                                                    )
                                                )
                                            }
                                )
                            }

                    members =
                        loaded.members
                            .map {
                                    member ->

                                ActiveMember(
                                    uid =
                                        member.uid,
                                    name =
                                        member.name,
                                    playerId =
                                        member.playerId,
                                    role =
                                        member.role,
                                    active =
                                        member.active
                                )
                            }

                    requestsLoaded =
                        true

                    membersLoaded =
                        true

                    errorText =
                        null
                },
                onError = {
                        message ->

                    requestsLoaded =
                        true

                    membersLoaded =
                        true

                    if (
                        requests.isEmpty() &&
                        members.isEmpty()
                    ) {
                        errorText =
                            message.ifBlank {
                                "Не удалось загрузить пользователей"
                            }
                    }
                }
            )
    }

    fun approve(
        request: PendingAccessRequest,
        slot: UserSlot
    ) {

        if (
            actionUid !=
            null
        ) {
            return
        }

        val user =
            DurakAuthSession.current()

        if (
            user ==
            null
        ) {
            actionError =
                "Пользователь не авторизован"

            return
        }

        actionUid =
            request.uid

        actionError =
            null

        DurakServerApi
            .approveAdminUser(
                user =
                    user,
                requestUid =
                    request.uid,
                playerId =
                    slot.playerId,
                onSuccess = {
                    actionUid =
                        null

                    reloadKey++
                },
                onError = {
                        message ->

                    actionUid =
                        null

                    actionError =
                        message.ifBlank {
                            "Не удалось выдать доступ"
                        }
                }
            )
    }

    PokerScreen {
        PokerBackTextButton(onClick = onBack)

        Spacer(modifier = Modifier.height(3.dp))

        UsersHero()

        Spacer(modifier = Modifier.height(18.dp))

        when {
            !requestsLoaded || !membersLoaded -> {
                Row(
                    modifier = Modifier.fillMaxWidth(),
                    horizontalArrangement = Arrangement.Center
                ) {
                    CircularProgressIndicator(
                        color = PokerPalette.CrimsonBright
                    )
                }
            }

            errorText != null -> {
                PokerPanel {
                    Text(
                        text = errorText!!,
                        color = PokerPalette.Danger,
                        fontSize = 14.sp
                    )
                }
            }

            else -> {
                UsersSectionTitle("ЗАЯВКИ НА ДОСТУП")

                Spacer(modifier = Modifier.height(10.dp))

                if (requests.isEmpty()) {
                    Surface(
                        modifier = Modifier.fillMaxWidth(),
                        color = Color(0xF2070B09),
                        border = BorderStroke(
                            1.dp,
                            PokerPalette.GoldDark
                        ),
                        shape = RoundedCornerShape(15.dp)
                    ) {
                        Text(
                            text =
                                "Тишина. Новых желающих ворваться за стол нет.",
                            modifier = Modifier.padding(14.dp),
                            color = PokerPalette.TextSecondary,
                            fontSize = 12.sp
                        )
                    }
                } else {
                    requests.forEach { request ->
                        PendingRequestCard(
                            request = request,
                            members = members,
                            busy = actionUid == request.uid,
                            onApprove = { slot ->
                                approve(request, slot)
                            }
                        )

                        Spacer(modifier = Modifier.height(10.dp))
                    }
                }

                if (actionError != null) {
                    Text(
                        text = actionError!!,
                        color = PokerPalette.Danger,
                        fontSize = 12.sp
                    )
                }

                Spacer(modifier = Modifier.height(18.dp))

                UsersSectionTitle("УЖЕ ЗА СТОЛОМ")

                Spacer(modifier = Modifier.height(10.dp))

                if (members.isEmpty()) {
                    Text(
                        text = "Допущенных пользователей не найдено",
                        color = PokerPalette.TextSecondary,
                        fontSize = 12.sp
                    )
                } else {
                    members.forEach { member ->
                        ActiveMemberCard(member)

                        Spacer(modifier = Modifier.height(8.dp))
                    }
                }
            }
        }

        Spacer(modifier = Modifier.height(12.dp))

        PokerBottomBackButton(onClick = onBack)
    }
}

@Composable
private fun UsersHero() {
    Card(
        modifier = Modifier
            .fillMaxWidth()
            .height(150.dp),
        colors = CardDefaults.cardColors(
            containerColor = Color(0xF2070908)
        ),
        border = BorderStroke(
            1.dp,
            PokerPalette.GoldDark
        ),
        shape = RoundedCornerShape(18.dp)
    ) {
        Box(
            modifier = Modifier.fillMaxSize()
        ) {
            Image(
                painter = painterResource(
                    id = R.drawable.gothic_users_jester
                ),
                contentDescription = null,
                contentScale = ContentScale.Fit,
                modifier = Modifier
                    .align(Alignment.CenterEnd)
                    .fillMaxHeight()
                    .width(170.dp)
            )

            Column(
                modifier = Modifier
                    .fillMaxSize()
                    .padding(
                        start = 16.dp,
                        top = 16.dp,
                        end = 125.dp,
                        bottom = 12.dp
                    )
            ) {
                Text(
                    text = "ПОЛЬЗОВАТЕЛИ",
                    color = PokerPalette.TextPrimary,
                    fontFamily = PokerDisplayFont,
                    fontSize = 20.sp,
                    fontWeight = FontWeight.Black,
                    maxLines = 1
                )

                Spacer(modifier = Modifier.height(5.dp))

                Text(
                    text = "КТО ДОПУЩЕН\nК ЭТОМУ БАЛАГАНУ",
                    color = PokerPalette.CrimsonBright,
                    fontSize = 10.5.sp,
                    lineHeight = 14.sp,
                    fontWeight = FontWeight.Black
                )

                Spacer(modifier = Modifier.height(6.dp))

                Text(
                    text = "Админ решает, кто кем будет.",
                    color = PokerPalette.Gold,
                    fontSize = 9.5.sp
                )
            }
        }
    }
}

@Composable
private fun UsersSectionTitle(
    text: String
) {
    Row(
        modifier = Modifier.fillMaxWidth(),
        verticalAlignment = Alignment.CenterVertically
    ) {
        Text(
            text = text,
            color = PokerPalette.CrimsonBright,
            fontSize = 11.sp,
            fontWeight = FontWeight.Black
        )

        Spacer(modifier = Modifier.width(9.dp))

        Box(
            modifier = Modifier
                .weight(1f)
                .height(1.dp)
                .background(PokerPalette.GoldDark)
        )
    }
}

@Composable
private fun PendingRequestCard(
    request: PendingAccessRequest,
    members: List<ActiveMember>,
    busy: Boolean,
    onApprove: (UserSlot) -> Unit
) {
    Surface(
        modifier = Modifier.fillMaxWidth(),
        color = Color(0xF2070B09),
        border = BorderStroke(
            1.dp,
            PokerPalette.Crimson
        ),
        shape = RoundedCornerShape(16.dp)
    ) {
        Column(
            modifier = Modifier.padding(13.dp)
        ) {
            Row(
                verticalAlignment = Alignment.CenterVertically
            ) {
                Image(
                    painter = painterResource(
                        id = R.drawable.gothic_user_badge
                    ),
                    contentDescription = null,
                    modifier = Modifier.size(48.dp),
                    contentScale = ContentScale.Fit
                )

                Spacer(modifier = Modifier.width(9.dp))

                Column(
                    modifier = Modifier.weight(1f)
                ) {
                    Text(
                        text = request.name,
                        color = PokerPalette.TextPrimary,
                        fontSize = 15.sp,
                        fontWeight = FontWeight.Black,
                        maxLines = 1,
                        overflow = TextOverflow.Ellipsis
                    )

                    Text(
                        text = request.email,
                        color = PokerPalette.TextSecondary,
                        fontSize = 10.sp,
                        maxLines = 1,
                        overflow = TextOverflow.Ellipsis
                    )
                }

                PokerBadge(
                    text = if (busy) "..." else "ЖДЁТ"
                )
            }

            Spacer(modifier = Modifier.height(10.dp))

            Text(
                text = "КЕМ ПУСКАЕМ:",
                color = PokerPalette.Gold,
                fontSize = 9.5.sp,
                fontWeight = FontWeight.Black
            )

            Spacer(modifier = Modifier.height(7.dp))

            userSlots.chunked(2).forEach { row ->
                Row(
                    modifier = Modifier.fillMaxWidth(),
                    horizontalArrangement =
                        Arrangement.spacedBy(7.dp)
                ) {
                    row.forEach { slot ->
                        val occupied =
                            members.any {
                                it.active &&
                                    it.playerId == slot.playerId
                            }

                        Column(
                            modifier = Modifier.weight(1f)
                        ) {
                            PokerSecondaryButton(
                                text =
                                    if (occupied) {
                                        "${slot.name} ✓"
                                    } else {
                                        slot.name
                                    },
                                enabled = !busy && !occupied,
                                onClick = {
                                    onApprove(slot)
                                }
                            )

                            Text(
                                text =
                                    when (slot.role) {
                                        "admin" -> "админ"
                                        "scorekeeper" -> "счётовод"
                                        else -> "наблюдатель"
                                    },
                                color = PokerPalette.TextSecondary,
                                fontSize = 8.5.sp,
                                modifier = Modifier.padding(
                                    start = 4.dp,
                                    top = 2.dp
                                )
                            )
                        }
                    }
                }

                Spacer(modifier = Modifier.height(7.dp))
            }
        }
    }
}

@Composable
private fun ActiveMemberCard(
    member: ActiveMember
) {
    val roleText =
        when (member.role) {
            "admin" -> "АДМИН"
            "scorekeeper" -> "СЧЁТОВОД"
            else -> "НАБЛЮДАТЕЛЬ"
        }

    Surface(
        modifier = Modifier.fillMaxWidth(),
        color = Color(0xF2070B09),
        border = BorderStroke(
            1.dp,
            if (member.active) {
                PokerPalette.GoldDark
            } else {
                PokerPalette.CrimsonDark
            }
        ),
        shape = RoundedCornerShape(14.dp)
    ) {
        Row(
            modifier = Modifier.padding(
                horizontal = 13.dp,
                vertical = 10.dp
            ),
            verticalAlignment = Alignment.CenterVertically
        ) {
            Text(
                text =
                    when (member.playerId) {
                        "denis" -> "♠"
                        "dmitry" -> "♣"
                        "rybka" -> "♥"
                        "masha" -> "♦"
                        else -> "☠"
                    },
                color =
                    if (
                        member.playerId == "rybka" ||
                        member.playerId == "masha"
                    ) {
                        PokerPalette.CrimsonBright
                    } else {
                        PokerPalette.Gold
                    },
                fontSize = 25.sp,
                fontWeight = FontWeight.Black
            )

            Spacer(modifier = Modifier.width(10.dp))

            Column(
                modifier = Modifier.weight(1f)
            ) {
                Text(
                    text = member.name,
                    color = PokerPalette.TextPrimary,
                    fontSize = 15.sp,
                    fontWeight = FontWeight.Bold
                )

                Text(
                    text = member.playerId,
                    color = PokerPalette.TextSecondary,
                    fontSize = 9.sp
                )
            }

            Text(
                text = roleText,
                color =
                    if (member.role == "admin") {
                        PokerPalette.CrimsonBright
                    } else {
                        PokerPalette.Gold
                    },
                fontSize = 9.5.sp,
                fontWeight = FontWeight.Black
            )
        }
    }
}
