package tk.zwander.common.compose.settings

import android.content.SharedPreferences
import androidx.compose.animation.*
import androidx.compose.animation.core.animateFloatAsState
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.*
import androidx.compose.material3.Icon
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.runtime.*
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.alpha
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.painter.Painter
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextOverflow
import androidx.compose.ui.unit.dp

open class BasePreference<ValueType>(
    val title: @Composable () -> String,
    val summary: @Composable () -> String?,
    val key: @Composable () -> String,
    val icon: @Composable () -> Painter?,
    val defaultValue: @Composable () -> ValueType,
    val onClick: (() -> Unit)? = null,
    val widget: (@Composable (Modifier) -> Unit)? = null,
    val widgetPosition: @Composable () -> WidgetPosition = { WidgetPosition.END },
    val enabled: @Composable () -> Boolean = { true },
    val visible: @Composable () -> Boolean = { true },
    val badge: (@Composable () -> Unit)? = null,
    val preferences: SharedPreferences? = null,
) {
    @Composable
    open fun Render(modifier: Modifier) {
        BasePreferenceLayout(
            title = title(),
            summary = summary(),
            modifier = modifier,
            icon = icon(),
            onClick = onClick,
            widget = widget,
            widgetPosition = widgetPosition(),
            enabled = enabled(),
            badge = badge,
        )
    }
}

@Composable
fun BasePreferenceLayout(
    title: String,
    summary: String?,
    modifier: Modifier = Modifier,
    icon: Painter? = null,
    onClick: (() -> Unit)? = null,
    widget: (@Composable (Modifier) -> Unit)? = null,
    widgetPosition: WidgetPosition = WidgetPosition.END,
    summaryMaxLines: Int = Int.MAX_VALUE,
    enabled: Boolean = true,
    titleTextColor: Color = Color.Unspecified,
    badge: (@Composable () -> Unit)? = null,
) {
    val animatedAlpha by animateFloatAsState(if (enabled) 1f else 0.7f)

    Surface(
        modifier = modifier,
    ) {
        Box {
            Column(
                modifier = Modifier
                    .alpha(animatedAlpha)
                    .then(
                        if (onClick != null) {
                            Modifier.clickable(onClick = onClick, enabled = enabled)
                        } else {
                            Modifier
                        },
                    )
                    .padding(vertical = 16.dp, horizontal = 8.dp),
                horizontalAlignment = Alignment.CenterHorizontally,
                verticalArrangement = Arrangement.spacedBy(16.dp),
            ) {
                Row(
                    modifier = Modifier.fillMaxWidth(),
                    verticalAlignment = Alignment.CenterVertically,
                    horizontalArrangement = Arrangement.spacedBy(16.dp),
                ) {
                    Box(
                        modifier = Modifier.width(48.dp),
                        contentAlignment = Alignment.Center,
                    ) {
                        icon?.let {
                            Icon(
                                painter = icon,
                                contentDescription = null,
                                modifier = Modifier.size(24.dp),
                            )
                        }
                    }

                    Column(
                        modifier = Modifier
                            .weight(1f),
                    ) {
                        Text(
                            text = title,
                            style = MaterialTheme.typography.bodyLarge,
                            fontWeight = FontWeight.Bold,
                            color = titleTextColor,
                        )

                        AnimatedVisibility(
                            visible = summary != null,
                            enter = fadeIn() + expandVertically(expandFrom = Alignment.Top),
                            exit = fadeOut() + shrinkVertically(shrinkTowards = Alignment.Top),
                        ) {
                            Spacer(modifier = Modifier.size(8.dp))

                            var tempSummary by remember { mutableStateOf(summary ?: "") }

                            LaunchedEffect(summary) {
                                if (summary != null) {
                                    tempSummary = summary
                                }
                            }

                            Text(
                                text = tempSummary,
                                maxLines = summaryMaxLines,
                                overflow = TextOverflow.Ellipsis,
                                style = MaterialTheme.typography.bodyMedium,
                            )
                        }

                        if (widgetPosition == WidgetPosition.BOTTOM_INLINE) {
                            Spacer(modifier = Modifier.size(8.dp))

                            widget?.invoke(Modifier)
                        }
                    }

                    if (widgetPosition == WidgetPosition.END) {
                        widget?.invoke(Modifier)
                    }
                }

                if (widgetPosition == WidgetPosition.BOTTOM) {
                    widget?.invoke(Modifier)
                }
            }

            badge?.let {
                Box(
                    modifier = Modifier.align(Alignment.TopEnd)
                        .padding(top = 8.dp, end = 8.dp),
                ) {
                    it()
                }
            }
        }
    }
}

enum class WidgetPosition {
    END,
    BOTTOM,
    BOTTOM_INLINE,
    ;
}
