package com.pixelized.desktop.lwa.ui.screen.admin.character.list

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.fillMaxHeight
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.material.Button
import androidx.compose.material.Icon
import androidx.compose.material.Surface
import androidx.compose.material.Text
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.Add
import androidx.compose.runtime.Composable
import androidx.compose.runtime.State
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.input.key.Key
import androidx.compose.ui.input.key.KeyEventType
import androidx.compose.ui.input.key.key
import androidx.compose.ui.input.key.type
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.LayoutDirection
import androidx.compose.ui.unit.dp
import androidx.compose.ui.zIndex
import com.pixelized.desktop.lwa.LocalBlurController
import com.pixelized.desktop.lwa.ui.composable.character.alterteration.CharacterSheetAlterationDialog
import com.pixelized.desktop.lwa.ui.composable.character.alterteration.CharacterSheetAlterationDialogViewModel
import com.pixelized.desktop.lwa.ui.composable.character.characteristic.CharacterSheetCharacteristicDialog
import com.pixelized.desktop.lwa.ui.composable.character.characteristic.CharacterSheetCharacteristicDialogViewModel
import com.pixelized.desktop.lwa.ui.composable.character.diminished.CharacterSheetDiminishedDialog
import com.pixelized.desktop.lwa.ui.composable.character.diminished.CharacterSheetDiminishedDialogViewModel
import com.pixelized.desktop.lwa.ui.composable.key.KeyHandler
import com.pixelized.desktop.lwa.ui.composable.textfield.LwaTextFieldUio
import com.pixelized.desktop.lwa.ui.navigation.screen.LocalScreenController
import com.pixelized.desktop.lwa.ui.navigation.screen.destination.gamemaster.navigateToGameMasterCharacterEditPage
import com.pixelized.desktop.lwa.ui.navigation.screen.destination.navigateToLevelScreen
import com.pixelized.desktop.lwa.ui.screen.campaign.player.detail.CharacterDetailPanel
import com.pixelized.desktop.lwa.ui.screen.campaign.player.detail.CharacterDetailPanelViewModel
import com.pixelized.desktop.lwa.ui.screen.campaign.player.detail.DetailPanelUio
import com.pixelized.desktop.lwa.ui.screen.campaign.player.detail.rememberTransitionAnimation
import com.pixelized.desktop.lwa.ui.screen.admin.common.GMFilterHeader
import com.pixelized.desktop.lwa.ui.screen.admin.common.tag.GMTagUio
import com.pixelized.desktop.lwa.ui.theme.color.component.LwaButtonColors
import kotlinx.coroutines.launch
import lwacharactersheet.composeapp.generated.resources.Res
import lwacharactersheet.composeapp.generated.resources.game_master__create_character_sheet
import org.jetbrains.compose.resources.stringResource
import org.koin.compose.viewmodel.koinViewModel

@Composable
fun GMCharacterPage(
    viewModel: GMCharacterViewModel = koinViewModel(),
    characterDetailViewModel: CharacterDetailPanelViewModel = koinViewModel(),
    characteristicDialogViewModel: CharacterSheetCharacteristicDialogViewModel = koinViewModel(),
    dismissedViewModel: CharacterSheetDiminishedDialogViewModel = koinViewModel(),
    alterationViewModel: CharacterSheetAlterationDialogViewModel = koinViewModel(),
) {
    val screens = LocalScreenController.current
    val blurController = LocalBlurController.current
    val scope = rememberCoroutineScope()

    val characters = viewModel.characters.collectAsState()
    val tags = viewModel.tags.collectAsState()

    Box {
        GMCharacterContent(
            filter = viewModel.filter,
            tags = tags,
            characters = characters,
            onTag = viewModel::onTag,
            onCharacterAction = viewModel::onCharacterAction,
            onCharacterSheetDetail = { characterSheetId ->
                scope.launch {
                    characterDetailViewModel.showCharacter(
                        characterSheetId = characterSheetId,
                        panel = DetailPanelUio.Sheet,
                    )
                }
            },
            onCharacterSheetEdit = { characterSheetId ->
                scope.launch {
                    characterDetailViewModel.editCharacter(
                        characterSheetId = characterSheetId,
                        screens = screens,
                    )
                }
            },
            onCharacterSheetCreate = {
                screens.navigateToGameMasterCharacterEditPage(
                    characterSheetId = null
                )
            },
        )

        CharacterDetailPanel(
            modifier = Modifier
                .align(alignment = Alignment.TopEnd)
                .padding(all = 8.dp)
                .width(width = 128.dp * 4)
                .fillMaxHeight(),
            transitionSpec = rememberTransitionAnimation(direction = LayoutDirection.Rtl),
            detailPanelViewModel = characterDetailViewModel,
            characterDiminishedViewModel = dismissedViewModel,
            characteristicDialogViewModel = characteristicDialogViewModel,
            alterationViewModel = alterationViewModel,
            onLevelUp = {
                screens.navigateToLevelScreen(characterSheetId = it)
            },
        )

        CharacterSheetCharacteristicDialog(
            dialog = characteristicDialogViewModel.statChangeDialog,
            onConfirm = { dialog ->
                scope.launch {
                    characteristicDialogViewModel.changeSubCharacteristic(
                        characterSheetId = dialog.characterSheetId,
                        characteristic = dialog.characteristic,
                        useArmor= dialog.enableArmor?.checked?.value == true,
                        value = dialog.value.valueFlow.value.toIntOrNull() ?: 0,
                    )
                    characteristicDialogViewModel.hideSubCharacteristicDialog()
                    blurController.hide()
                }
            },
            onSwapSign = {
                characteristicDialogViewModel.swapCharacteristicSign()
            },
            onDismissRequest = {
                characteristicDialogViewModel.hideSubCharacteristicDialog()
                blurController.hide()
            },
        )

        CharacterSheetDiminishedDialog(
            dialog = dismissedViewModel.diminishedDialog,
            onConfirm = { diminished ->
                scope.launch {
                    dismissedViewModel.changeDiminished(
                        dialog = diminished
                    )
                    blurController.hide()
                    dismissedViewModel.hideDiminishedDialog()
                }
            },
            onDismissRequest = {
                blurController.hide()
                dismissedViewModel.hideDiminishedDialog()
            },
        )

        CharacterSheetAlterationDialog(
            dialog = alterationViewModel.alterationDialog.collectAsState(),
            onTag = {
                alterationViewModel.selectedTag(id = it)
            },
            onAlteration = { characterSheetId, alterationId, active ->
                scope.launch {
                    alterationViewModel.toggleAlteration(characterSheetId, alterationId, active)
                }
            },
            onDismissRequest = {
                blurController.hide()
                alterationViewModel.hide()
            },
        )
    }

    GameMasterCharacterKeyHandler(
        onDismissRequest = {
            characterDetailViewModel.hideCharacter()
        }
    )
}

@Composable
fun GMCharacterContent(
    modifier: Modifier = Modifier,
    padding: Dp = 8.dp,
    spacing: Dp = 8.dp,
    filter: LwaTextFieldUio,
    tags: State<List<GMTagUio>>,
    characters: State<List<GMCharacterItemUio>>,
    onTag: (String) -> Unit,
    onCharacterAction: (String, GMCharacterItemUio.Action) -> Unit,
    onCharacterSheetDetail: (String) -> Unit,
    onCharacterSheetEdit: (String) -> Unit,
    onCharacterSheetCreate: () -> Unit,
) {
    Column(
        modifier = modifier,
    ) {
        Surface(
            modifier = Modifier.zIndex(1f), // avoid display issue with LazyColumnScope.animateItem()
            elevation = 1.dp,
        ) {
            GMFilterHeader(
                padding = padding,
                spacing = spacing,
                filter = filter,
                tags = tags,
                onTag = onTag,
            )
        }
        Box(
            modifier = Modifier.fillMaxWidth().weight(1f),
        ) {
            LazyColumn(
                modifier = Modifier.matchParentSize(),
                contentPadding = remember {
                    PaddingValues(
                        start = padding,
                        top = padding,
                        end = padding,
                        bottom = padding + 48.dp + padding,
                    )
                },
                verticalArrangement = Arrangement.spacedBy(space = spacing),
            ) {
                items(
                    items = characters.value,
                    key = { it.characterSheetId },
                ) { character ->
                    GMCharacter(
                        modifier = Modifier
                            .fillMaxWidth()
                            .animateItem(),
                        character = character,
                        onClick = {
                            onCharacterSheetEdit(character.characterSheetId)
                        },
                        onSecondary = {
                            onCharacterSheetDetail(character.characterSheetId)
                        },
                        onAction = { action ->
                            onCharacterAction(character.characterSheetId, action)
                        },
                        onTag = onTag,
                    )
                }
            }
            Row(
                modifier = Modifier
                    .align(alignment = Alignment.BottomEnd)
                    .padding(all = padding),
                horizontalArrangement = Arrangement.SpaceBetween,
            ) {
                Button(
                    colors = LwaButtonColors(),
                    shape = CircleShape,
                    onClick = onCharacterSheetCreate,
                ) {
                    Text(
                        modifier = Modifier.padding(end = 4.dp),
                        text = stringResource(Res.string.game_master__create_character_sheet),
                    )
                    Icon(
                        imageVector = Icons.Default.Add,
                        contentDescription = null,
                    )
                }
            }
        }
    }
}

@Composable
private fun GameMasterCharacterKeyHandler(
    onDismissRequest: () -> Unit,
) {
    KeyHandler {
        when {
            it.type == KeyEventType.KeyDown && it.key == Key.Escape -> {
                onDismissRequest()
                true
            }

            else -> false
        }
    }
}