package com.laseroptek.raman.ui.common.lock

import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.text.BasicTextField
import androidx.compose.foundation.text.KeyboardActions
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material3.LocalTextStyle
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.DisposableEffect
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.focus.FocusRequester
import androidx.compose.ui.focus.focusRequester
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalFocusManager
import androidx.compose.ui.text.TextRange
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.input.ImeAction
import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.text.input.TextFieldValue
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.Dp
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.laseroptek.raman.utils.ext.px
import kotlinx.coroutines.delay
import timber.log.Timber

@Composable
fun OTPBox(
    modifier: Modifier = Modifier,
    keyboardType: KeyboardType = KeyboardType.NumberPassword,
    pinLength: Int = 6,
    pinValue: String = "", // The actual PIN value
    onPinValueChanged: (String) -> Unit,
    onDone: (() -> Unit)? = null,
    obscuringCharacter: Char = '*',
    digitSpacing: Dp = 38.px.dp,
    textStyle: TextStyle = LocalTextStyle.current.copy(fontSize = 32.px.sp, textAlign = TextAlign.Center),
    autoShowKeyboard: Boolean = true,
) {
    val focusManager = LocalFocusManager.current
    val focusRequester = remember { FocusRequester() }

    Column(
        modifier = Modifier
            .fillMaxSize(),
        horizontalAlignment = Alignment.CenterHorizontally,
        verticalArrangement = Arrangement.Center
    ) {
        var textFieldValue by remember(pinValue) {
            mutableStateOf(
                TextFieldValue(
                    text = pinValue,
                    selection = TextRange(pinValue.length) // Place cursor at the end
                )
            )
        }

        // Used to visually represent the PIN with obscuring characters
        val displayValue = obscuringCharacter.toString().repeat(textFieldValue.text.length)

        LaunchedEffect(Unit) {
            if (autoShowKeyboard) {
                delay(100)
                Timber.d("focusRequester.requestFocus()")
                focusRequester.requestFocus()
            } else {
                focusManager.clearFocus(force = true) // Hide the keyboard
            }
        }

        DisposableEffect(Unit) {
            onDispose {
                Timber.d("MyComposable is being disposed!")
                //focusManager.clearFocus(force = true) // Hide the keyboard
            }
        }

        if (!autoShowKeyboard) {
            focusManager.clearFocus(force = true) // Hide the keyboard
        }

        BasicTextField(
            value = textFieldValue.copy(text = displayValue), // Display asterisks
            onValueChange = { newTextFieldValue ->
                //val newText = newTextFieldValue.text.filter { it.isDigit() } // Allow only digits
                val newText = newTextFieldValue.text
                val currentActualText = textFieldValue.text
                val enteredChar = newText.lastOrNull()?.toString() ?: ""
                var updatedPin = currentActualText

                Timber.d("newText: ${newText}")
                Timber.d("enteredChar: ${enteredChar}")

                if (newText.length > currentActualText.length) { // Character added
                    if (currentActualText.length < pinLength) {
                        updatedPin += enteredChar
                    } else {
                        // Replace last character if length limit is reached
                        updatedPin = currentActualText.dropLast(1) + enteredChar
                    }
                } else if (newText.length < currentActualText.length) { // Character deleted (backspace)
                    updatedPin = currentActualText.dropLast(1)
                }
                // Ensure pin does not exceed maxLength (should be handled by above logic mostly)
                if (updatedPin.length > pinLength) {
                    updatedPin = updatedPin.take(pinLength)
                }

                textFieldValue = TextFieldValue(
                    text = updatedPin, // Store actual digits internally
                    selection = TextRange(updatedPin.length)
                )

                Timber.d("updatedPin: ${updatedPin}")
                onPinValueChanged(updatedPin)
            },
            modifier = modifier.focusRequester(focusRequester),
            keyboardOptions = KeyboardOptions(
                keyboardType = keyboardType, // KeyboardType.NumberPassword,     // KeyboardType.Text, // KeyboardType.NumberPassword, // Or KeyboardType.Number
                //imeAction = if (onDone != null) ImeAction.Done else ImeAction.Default
                imeAction = ImeAction.Done,
                //autoCorrect = false
            ),
            keyboardActions = KeyboardActions(
                onDone = {
                    Timber.d("onDone()")
                    onDone?.invoke()
                    // focusManager.clearFocus() // Hide the keyboard
                }
            ),
            textStyle = textStyle.copy(color = Color.Transparent), // Make actual input transparent
            decorationBox = {
                // Custom decoration to show asterisks and handle spacing
                Row(
                    horizontalArrangement = Arrangement.Center,
                    verticalAlignment = Alignment.CenterVertically
                ) {
                    Timber.d("displayValue: ${displayValue}")
                    Timber.d("pinLength: ${pinLength}, displayValue.length: ${displayValue.length}")

                    displayValue.forEachIndexed { index, char ->
                        Text(
                            text = char.toString(),
                            style = textStyle,
                            modifier = Modifier
                                .fillMaxSize()
                                .weight(1f)
                                .padding(top = 10.px.dp),
                            textAlign = TextAlign.Center
                        )
                    }

                    // Fill remaining spaces if pin is not complete (optional)
                    repeat(pinLength - displayValue.length) {
                        Text(
                            text = "●", // Placeholder for empty slots, or use a different char
                            style = textStyle,
                            modifier = Modifier
                                .fillMaxSize()
                                .weight(1f)
                                .padding(bottom = 30.px.dp),
                            textAlign = TextAlign.Center
                        )
                    }
                }
            }
        )
    }
}