package com.pixelized.desktop.lwa.ui.screen.admin.item.edit

import androidx.compose.animation.AnimatedContent
import androidx.compose.animation.SizeTransform
import androidx.compose.animation.animateContentSize
import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.animation.fadeIn
import androidx.compose.animation.fadeOut
import androidx.compose.animation.togetherWith
import androidx.compose.foundation.background
import androidx.compose.foundation.interaction.MutableInteractionSource
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
import androidx.compose.foundation.layout.Row
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.material.DropdownMenuItem
import androidx.compose.material.ExperimentalMaterialApi
import androidx.compose.material.ExposedDropdownMenuBox
import androidx.compose.material.Icon
import androidx.compose.material.IconButton
import androidx.compose.material.MaterialTheme
import androidx.compose.material.Text
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.filled.ArrowDropDown
import androidx.compose.material.icons.filled.Close
import androidx.compose.runtime.Composable
import androidx.compose.runtime.Immutable
import androidx.compose.runtime.Stable
import androidx.compose.runtime.State
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import com.pixelized.desktop.lwa.ui.theme.lwa
import com.pixelized.desktop.lwa.utils.extention.calculateHorizontalPaddings
import com.pixelized.desktop.lwa.utils.extention.ribbon
import kotlinx.coroutines.flow.StateFlow

@Stable
data class GMAlterationFieldItemUio(
    val key: String,
    val value: StateFlow<Field?>,
    val error: StateFlow<String?>,
    val menu: List<Field>,
) {
    @Stable
    data class Field(
        val id: String,
        val label: String,
    )
}

@Immutable
data object AlterationFieldItemDefault {
    @Stable
    val padding = PaddingValues(horizontal = 16.dp, vertical = 8.dp)

    @Stable
    val spacing = 8.dp
}

@Composable
fun GMAlterationFieldItem(
    modifier: Modifier = Modifier,
    padding: PaddingValues = AlterationFieldItemDefault.padding,
    spacing: Dp = AlterationFieldItemDefault.spacing,
    field: GMAlterationFieldItemUio,
    onAlteration: (GMAlterationFieldItemUio.Field?) -> Unit,
    onRemoveField: (String) -> Unit,
) {
    val error = field.error.collectAsState()
    val menu = remember { mutableStateOf(false) }

    AlterationFieldContent(
        modifier = modifier,
        padding = padding,
        spacing = spacing,
        isOpen = menu,
        isError = error,
        field = field,
        onOpenStateChange = { menu.value = it },
        onAlteration = {
            menu.value = false
            onAlteration(it)
        },
        onRemoveField = onRemoveField,
    )
}

@Composable
@OptIn(ExperimentalMaterialApi::class)
fun AlterationFieldContent(
    modifier: Modifier = Modifier,
    padding: PaddingValues,
    spacing: Dp,
    isOpen: State<Boolean>,
    isError: State<String?>,
    field: GMAlterationFieldItemUio,
    onOpenStateChange: (Boolean) -> Unit,
    onAlteration: (GMAlterationFieldItemUio.Field?) -> Unit,
    onRemoveField: (String) -> Unit,
) {
    val horizontal = padding.calculateHorizontalPaddings()

    Column(
        modifier = Modifier
            .animateContentSize()
            .then(other = modifier),
    ) {
        Row(
            horizontalArrangement = Arrangement.spacedBy(space = spacing),
        ) {
            ExposedDropdownMenuBox(
                modifier = Modifier
                    .weight(weight = 1f)
                    .clip(
                        shape = MaterialTheme.shapes.small,
                    )
                    .background(
                        color = MaterialTheme.lwa.colorScheme.elevated.base1dp,
                    )
                    .ribbon(
                        color = when (isError.value) {
                            null -> Color.Transparent
                            else -> MaterialTheme.lwa.colorScheme.base.error
                        }
                    ),
                expanded = isOpen.value,
                onExpandedChange = onOpenStateChange,
            ) {
                Row(
                    modifier = Modifier
                        .fillMaxWidth()
                        .height(height = 48.dp)
                        .padding(paddingValues = horizontal),
                    verticalAlignment = Alignment.CenterVertically,
                ) {
                    AnimatedContent(
                        modifier = Modifier.weight(1f),
                        targetState = field.value.value?.label,
                        transitionSpec = {
                            val enter = fadeIn()
                            val exit = fadeOut()
                            enter togetherWith exit using SizeTransform(clip = false)
                        },
                    ) {
                        Text(
                            style = MaterialTheme.typography.body1,
                            overflow = TextOverflow.Ellipsis,
                            maxLines = 1,
                            text = it ?: "",
                        )
                    }
                    val rotation = animateFloatAsState(
                        targetValue = if (isOpen.value) -180f else 0f,
                    )
                    Icon(
                        modifier = Modifier.graphicsLayer { rotationZ = rotation.value },
                        imageVector = Icons.Default.ArrowDropDown,
                        contentDescription = null
                    )
                }
                ExposedDropdownMenu(
                    modifier = Modifier.heightIn(max = 480.dp),
                    expanded = isOpen.value,
                    onDismissRequest = { onOpenStateChange(false) }
                ) {
                    field.menu.forEach {
                        DropdownMenuItem(
                            onClick = { onAlteration(it) },
                            enabled = true,
                            interactionSource = remember { MutableInteractionSource() },
                            content = {
                                Text(
                                    color = MaterialTheme.colors.primary,
                                    text = it.label,
                                )
                            },
                        )
                    }
                }
            }

            IconButton(
                modifier = Modifier
                    .size(size = 48.dp)
                    .background(
                        color = MaterialTheme.lwa.colorScheme.elevated.base1dp,
                        shape = MaterialTheme.shapes.small,
                    ),
                onClick = { onRemoveField(field.key) },
            ) {
                Icon(
                    imageVector = Icons.Default.Close,
                    tint = MaterialTheme.lwa.colorScheme.base.primary,
                    contentDescription = null,
                )
            }
        }
        isError.value?.let {
            Text(
                style = MaterialTheme.typography.caption,
                color = MaterialTheme.colors.error,
                text = it
            )
        }
    }
}