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.BoxWithConstraints
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.heightIn
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.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.Brush
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.platform.LocalDensity
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
import kotlin.math.roundToInt

data class HistoryGame(
    val id: String,
    val type: String,
    val isTest: Boolean,
    val targetScore: Int,
    val players: List<GamePlayer>,
    val finalScores: Map<String, Int>,
    val loserId: String,
    val loserName: String,
    val loserGender: String,
    val startedAt: Timestamp,
    val finishedAt: Timestamp
)

@Composable
fun HistoryScreen(
    access: UserAccess,
    onBack: () -> Unit
) {

    BackHandler(
        onBack =
            onBack
    )

    var games by remember {
        mutableStateOf<List<HistoryGame>>(
            emptyList()
        )
    }

    var isLoading by remember {
        mutableStateOf(true)
    }

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

    LaunchedEffect(Unit) {

        val user =
            DurakAuthSession.current()

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

            isLoading =
                false

            return@LaunchedEffect
        }

        DurakServerApi
            .loadFinishedGames(
                user =
                    user,
                onSuccess = {
                        serverGames ->

                    val loadedGames =
                        serverGames
                            .mapNotNull {
                                    game ->

                                if (
                                    game.startedAtEpochMillis <=
                                    0L ||
                                    game.finishedAtEpochMillis <=
                                    0L
                                ) {
                                    return@mapNotNull null
                                }

                                HistoryGame(
                                    id =
                                        game.id,
                                    type =
                                        game.gameType,
                                    isTest =
                                        game.isTest,
                                    targetScore =
                                        game.targetScore,
                                    players =
                                        game.players.map {
                                                player ->

                                            GamePlayer(
                                                id =
                                                    player.id,
                                                name =
                                                    player.name,
                                                gender =
                                                    player.gender,
                                                isCore =
                                                    player.isCore,
                                                isGuest =
                                                    player.isGuest
                                            )
                                        },
                                    finalScores =
                                        game.finalScores,
                                    loserId =
                                        game.loserId,
                                    loserName =
                                        game.loserName,
                                    loserGender =
                                        game.loserGender,
                                    startedAt =
                                        Timestamp(
                                            Date(
                                                game.startedAtEpochMillis
                                            )
                                        ),
                                    finishedAt =
                                        Timestamp(
                                            Date(
                                                game.finishedAtEpochMillis
                                            )
                                        )
                                )
                            }
                            .sortedByDescending {
                                it.finishedAt.seconds
                            }

                    games =
                        if (
                            TEST_MODE
                        ) {
                            loadedGames
                        } else {
                            loadedGames
                                .filter {
                                    !it.isTest
                                }
                        }

                    errorText =
                        null

                    isLoading =
                        false
                },
                onError = {
                        message ->

                    if (
                        games.isEmpty()
                    ) {
                        errorText =
                            message.ifBlank {
                                "Не удалось загрузить историю"
                            }
                    }

                    isLoading =
                        false
                }
            )
    }

    val myGames =
        remember(
            games,
            access.playerId
        ) {
            games.filter {
                    game ->
                game.players.any {
                    it.id ==
                        access.playerId
                }
            }
        }

    val myLosses =
        remember(
            myGames,
            access.playerId
        ) {
            myGames.count {
                it.loserId ==
                    access.playerId
            }
        }

    val mySurvived =
        (
            myGames.size -
                myLosses
            )
            .coerceAtLeast(
                0
            )

    val survivedPercent =
        if (
            myGames.isEmpty()
        ) {
            0
        } else {
            (
                mySurvived.toDouble() /
                    myGames.size.toDouble() *
                    100.0
                )
                .roundToInt()
        }

    PokerScreen {

        PokerBackTextButton(
            text =
                "← Назад",
            onClick =
                onBack
        )

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

        Text(
            text =
                "ИСТОРИЯ",
            color =
                PokerPalette.TextPrimary,
            fontSize =
                31.sp,
            fontFamily =
                PokerDisplayFont,
            fontWeight =
                FontWeight.Black
        )

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

        HistoryHero()

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

        HistorySectionTitle(
            text =
                "НЕДАВНИЕ ПАРТИИ"
        )

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

        when {

            isLoading -> {

                Row(
                    modifier =
                        Modifier.fillMaxWidth(),
                    horizontalArrangement =
                        Arrangement.Center
                ) {

                    CircularProgressIndicator(
                        color =
                            PokerPalette.CrimsonBright
                    )
                }
            }

            errorText != null -> {

                PokerPanel {

                    Text(
                        text =
                            errorText!!,
                        color =
                            PokerPalette.Danger,
                        fontSize =
                            15.sp
                    )
                }
            }

            games.isEmpty() -> {

                PokerPanel {

                    Text(
                        text =
                            "Завершённых партий пока нет. Позор ещё не зафиксирован.",
                        color =
                            PokerPalette.TextPrimary,
                        fontSize =
                            15.sp
                    )
                }
            }

            else -> {

                games.forEach {
                        game ->

                    HistoryGothicCard(
                        game =
                            game
                    )

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

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

                HistorySectionTitle(
                    text =
                        "ТВОЯ ИСТОРИЯ В ЦИФРАХ"
                )

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

                HistorySummary(
                    played =
                        myGames.size,
                    survived =
                        mySurvived,
                    losses =
                        myLosses,
                    survivedPercent =
                        survivedPercent
                )
            }
        }

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

        PokerBottomBackButton(
            onClick =
                onBack
        )
    }
}

@Composable
private fun HistoryHero() {
    val fontScale = LocalDensity.current.fontScale
    val heroMinHeight =
        when {
            fontScale >= 1.30f -> 220.dp
            fontScale >= 1.15f -> 198.dp
            else -> 180.dp
        }

    Surface(
        modifier =
            Modifier
                .fillMaxWidth()
                .heightIn(min = heroMinHeight),
        color = Color(0xF2070908),
        border =
            BorderStroke(
                1.dp,
                PokerPalette.GoldDark
            ),
        shape = RoundedCornerShape(18.dp)
    ) {
        Box(
            modifier =
                Modifier
                    .fillMaxWidth()
                    .heightIn(min = heroMinHeight)
        ) {
            Image(
                painter =
                    painterResource(
                        id = R.drawable.gothic_history_jester
                    ),
                contentDescription = null,
                contentScale = ContentScale.Fit,
                modifier =
                    Modifier
                        .align(Alignment.CenterEnd)
                        .fillMaxHeight()
                        .width(195.dp)
            )

            Box(
                modifier =
                    Modifier
                        .align(Alignment.CenterEnd)
                        .fillMaxHeight()
                        .width(225.dp)
                        .background(
                            brush =
                                Brush.horizontalGradient(
                                    colors =
                                        listOf(
                                            Color(0xF2070908),
                                            Color(0xB0070908),
                                            Color.Transparent
                                        )
                                )
                        )
            )

            Column(
                modifier =
                    Modifier
                        .fillMaxWidth()
                        .padding(
                            start = 17.dp,
                            top = 22.dp,
                            end =
                                if (fontScale >= 1.25f) {
                                    76.dp
                                } else {
                                    140.dp
                                },
                            bottom = 14.dp
                        )
            ) {
                Text(
                    text = "ВСЕ ПАРТИИ —\nВСЕ ПОЗОРЫ",
                    color = PokerPalette.CrimsonBright,
                    fontSize =
                        if (fontScale >= 1.25f) {
                            18.sp
                        } else {
                            20.sp
                        },
                    lineHeight = 24.sp,
                    fontFamily = PokerDisplayFont,
                    fontWeight = FontWeight.Black,
                    maxLines = 4,
                    softWrap = true
                )

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

                Text(
                    text = "Архив побед над судьбой\nи официальных поражений",
                    color = PokerPalette.Gold,
                    fontSize = 13.sp,
                    lineHeight = 18.sp,
                    maxLines = 4,
                    softWrap = true
                )
            }
        }
    }
}

@Composable
private fun HistorySectionTitle(
    text: String
) {

    Row(
        modifier =
            Modifier.fillMaxWidth(),
        verticalAlignment =
            Alignment.CenterVertically
    ) {

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

        Text(
            text =
                text,
            modifier =
                Modifier.padding(
                    horizontal =
                        10.dp
                ),
            color =
                PokerPalette.CrimsonBright,
            fontSize =
                13.sp,
            fontWeight =
                FontWeight.Black,
            letterSpacing =
                1.2.sp
        )

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

@Composable
private fun HistoryGothicCard(
    game: HistoryGame
) {

    val loserWord =
        if (
            game.loserGender ==
            "female"
        ) {
            "проиграла"
        } else {
            "проиграл"
        }

    Surface(
        modifier =
            Modifier.fillMaxWidth(),
        color =
            Color(
                0xF2070B09
            ),
        border =
            BorderStroke(
                1.dp,
                PokerPalette.GoldDark
            ),
        shape =
            RoundedCornerShape(
                16.dp
            )
    ) {

        Column(
            modifier =
                Modifier.padding(
                    13.dp
                )
        ) {

            Row(
                modifier =
                    Modifier.fillMaxWidth(),
                verticalAlignment =
                    Alignment.CenterVertically
            ) {

                Image(
                    painter =
                        painterResource(
                            id =
                                if (
                                    game.type ==
                                    "classic"
                                ) {
                                    R.drawable.gothic_history_classic
                                } else {
                                    R.drawable.gothic_history_cards
                                }
                        ),
                    contentDescription =
                        null,
                    contentScale =
                        ContentScale.Fit,
                    modifier =
                        Modifier.size(
                            50.dp
                        )
                )

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

                Column(
                    modifier =
                        Modifier.weight(
                            1f
                        )
                ) {

                    Text(
                        text =
                            if (
                                game.type ==
                                "classic"
                            ) {
                                "КЛАССИЧЕСКАЯ ПАРТИЯ"
                            } else {
                                "ДРУГОЙ СОСТАВ"
                            },
                        color =
                            PokerPalette.TextPrimary,
                        fontSize =
                            13.sp,
                        fontWeight =
                            FontWeight.Black,
                        maxLines =
                            2,
                        softWrap =
                            true,
                        overflow =
                            TextOverflow.Ellipsis
                    )

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

                    Text(
                        text =
                            formatMoscowHistoryPeriod(
                                game.startedAt,
                                game.finishedAt
                            ),
                        color =
                            PokerPalette.Gold,
                        fontSize =
                            10.5.sp,
                        maxLines =
                            2
                    )
                }

                if (
                    game.isTest
                ) {

                    PokerBadge(
                        text =
                            "ТЕСТ"
                    )
                }
            }

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

            BoxWithConstraints(
                modifier = Modifier.fillMaxWidth()
            ) {
                val singleColumn =
                    maxWidth < 335.dp ||
                        LocalDensity.current.fontScale >= 1.28f

                if (singleColumn) {
                    Column(
                        modifier = Modifier.fillMaxWidth(),
                        verticalArrangement =
                            Arrangement.spacedBy(6.dp)
                    ) {
                        game.players.forEach { player ->
                            HistoryScoreCell(
                                name =
                                    if (player.isGuest) {
                                        "${player.name} · гость"
                                    } else {
                                        player.name
                                    },
                                score =
                                    game.finalScores[player.id] ?: 0,
                                isLoser =
                                    player.id == game.loserId,
                                modifier = Modifier.fillMaxWidth()
                            )
                        }
                    }
                } else {
                    Column(
                        modifier = Modifier.fillMaxWidth()
                    ) {
                        game.players
                            .chunked(2)
                            .forEach { rowPlayers ->
                                Row(
                                    modifier = Modifier.fillMaxWidth(),
                                    horizontalArrangement =
                                        Arrangement.spacedBy(7.dp)
                                ) {
                                    rowPlayers.forEach { player ->
                                        HistoryScoreCell(
                                            name =
                                                if (player.isGuest) {
                                                    "${player.name} · гость"
                                                } else {
                                                    player.name
                                                },
                                            score =
                                                game.finalScores[player.id] ?: 0,
                                            isLoser =
                                                player.id == game.loserId,
                                            modifier = Modifier.weight(1f)
                                        )
                                    }

                                    if (rowPlayers.size == 1) {
                                        Spacer(
                                            modifier = Modifier.weight(1f)
                                        )
                                    }
                                }

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

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

            Box(
                modifier =
                    Modifier
                        .fillMaxWidth()
                        .height(
                            1.dp
                        )
                        .background(
                            Color(
                                0xFF2A2419
                            )
                        )
            )

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

            Row(
                modifier =
                    Modifier.fillMaxWidth(),
                verticalAlignment =
                    Alignment.CenterVertically
            ) {

                Image(
                    painter =
                        painterResource(
                            id =
                                R.drawable.gothic_history_loser
                        ),
                    contentDescription =
                        null,
                    modifier =
                        Modifier.size(
                            42.dp
                        ),
                    contentScale =
                        ContentScale.Fit
                )

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

                Column(
                    modifier =
                        Modifier.weight(
                            1f
                        )
                ) {

                    Text(
                        text =
                            "ДУРАК: ${game.loserName}",
                        color =
                            PokerPalette.CrimsonBright,
                        fontSize =
                            14.sp,
                        fontWeight =
                            FontWeight.Black
                    )

                    Text(
                        text =
                            "${game.loserName} $loserWord • лимит ${game.targetScore}",
                        color =
                            PokerPalette.TextSecondary,
                        fontSize =
                            10.sp
                    )
                }
            }
        }
    }
}

@Composable
private fun HistoryScoreCell(
    name: String,
    score: Int,
    isLoser: Boolean,
    modifier: Modifier = Modifier
) {

    Surface(
        modifier =
            modifier,
        color =
            if (
                isLoser
            ) {
                Color(
                    0xFF220A09
                )
            } else {
                Color(
                    0xFF080D0B
                )
            },
        border =
            BorderStroke(
                1.dp,
                if (
                    isLoser
                ) {
                    PokerPalette.Crimson
                } else {
                    Color(
                        0xFF2A342D
                    )
                }
            ),
        shape =
            RoundedCornerShape(
                11.dp
            )
    ) {

        Row(
            modifier =
                Modifier.padding(
                    horizontal =
                        9.dp,
                    vertical =
                        7.dp
                ),
            verticalAlignment =
                Alignment.CenterVertically
        ) {

            Text(
                text =
                    name,
                color =
                    if (
                        isLoser
                    ) {
                        PokerPalette.CrimsonBright
                    } else {
                        PokerPalette.TextPrimary
                    },
                fontSize =
                    10.5.sp,
                fontWeight =
                    FontWeight.SemiBold,
                maxLines =
                    2,
                softWrap =
                    true,
                overflow =
                    TextOverflow.Ellipsis,
                modifier =
                    Modifier.weight(
                        1f
                    )
            )

            Text(
                text =
                    score.toString(),
                color =
                    if (
                        isLoser
                    ) {
                        PokerPalette.CrimsonBright
                    } else {
                        PokerPalette.GoldBright
                    },
                fontSize =
                    15.sp,
                fontWeight =
                    FontWeight.Black
            )
        }
    }
}

@Composable
private fun HistorySummary(
    played: Int,
    survived: Int,
    losses: Int,
    survivedPercent: Int
) {

    val items =
        listOf(
            Triple(
                R.drawable.gothic_history_crown,
                "ПАРТИЙ",
                played.toString()
            ),
            Triple(
                R.drawable.gothic_history_survivor,
                "ВЫЖИЛ",
                survived.toString()
            ),
            Triple(
                R.drawable.gothic_history_skull,
                "ПОРАЖЕНИЙ",
                losses.toString()
            ),
            Triple(
                R.drawable.gothic_history_card,
                "НЕ БЫЛ ДУРАКОМ",
                "$survivedPercent%"
            )
        )

    Surface(
        modifier =
            Modifier.fillMaxWidth(),
        color =
            Color(
                0xF2070B09
            ),
        border =
            BorderStroke(
                1.dp,
                PokerPalette.GoldDark
            ),
        shape =
            RoundedCornerShape(
                16.dp
            )
    ) {

        Column(
            modifier =
                Modifier.padding(
                    10.dp
                ),
            verticalArrangement =
                Arrangement.spacedBy(
                    8.dp
                )
        ) {

            items
                .chunked(
                    2
                )
                .forEach {
                        rowItems ->

                    Row(
                        modifier =
                            Modifier.fillMaxWidth(),
                        horizontalArrangement =
                            Arrangement.spacedBy(
                                8.dp
                            )
                    ) {

                        rowItems.forEach {
                                (icon, label, value) ->

                            Surface(
                                modifier =
                                    Modifier.weight(
                                        1f
                                    ),
                                color =
                                    Color(
                                        0xFF070B09
                                    ),
                                border =
                                    BorderStroke(
                                        1.dp,
                                        Color(
                                            0xFF2A2419
                                        )
                                    ),
                                shape =
                                    RoundedCornerShape(
                                        12.dp
                                    )
                            ) {

                                Row(
                                    modifier =
                                        Modifier.padding(
                                            9.dp
                                        ),
                                    verticalAlignment =
                                        Alignment.CenterVertically
                                ) {

                                    Image(
                                        painter =
                                            painterResource(
                                                id =
                                                    icon
                                            ),
                                        contentDescription =
                                            null,
                                        modifier =
                                            Modifier.size(
                                                42.dp
                                            ),
                                        contentScale =
                                            ContentScale.Fit
                                    )

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

                                    Column {

                                        Text(
                                            text =
                                                value,
                                            color =
                                                PokerPalette.GoldBright,
                                            fontSize =
                                                20.sp,
                                            fontWeight =
                                                FontWeight.Black
                                        )

                                        Text(
                                            text =
                                                label,
                                            color =
                                                PokerPalette.TextSecondary,
                                            fontSize =
                                                8.5.sp,
                                            fontWeight =
                                                FontWeight.Bold,
                                            maxLines =
                                                2
                                        )
                                    }
                                }
                            }
                        }
                    }
                }
        }
    }
}
