package dev.privacyllc.period.feature.lock

import android.content.res.Configuration
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.foundation.verticalScroll
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
import androidx.compose.runtime.Composable
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.semantics.LiveRegionMode
import androidx.compose.ui.semantics.liveRegion
import androidx.compose.ui.semantics.semantics
import androidx.compose.ui.text.input.ImeAction
import androidx.compose.ui.text.input.KeyboardCapitalization
import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.tooling.preview.Preview
import androidx.compose.ui.unit.dp
import androidx.hilt.lifecycle.viewmodel.compose.hiltViewModel
import androidx.lifecycle.compose.collectAsStateWithLifecycle
import dev.privacyllc.period.designsystem.PeriodTheme

/**
 * Behind "Forgot your PIN?", and it is a whole screen rather than a dialog
 * because it needs reading rather than dismissing.
 *
 * The copy tells the truth in the order that matters: this does not unlock
 * anything, it destroys what is stored, and it brings nothing back. It also says
 * the honest thing about the risk — anyone holding the phone can already do the
 * same from Android's own settings — so the choice is informed rather than
 * frightening.
 *
 * Confirmation is a typed word, not a press-and-hold. Typing is the more
 * accessible of the two, and the button stays enabled with an inline error on
 * press rather than being disabled, so somebody using a screen reader is told
 * *why* rather than meeting a control that silently does nothing.
 */
@Composable
fun ForgotPinScreen(
    onCancel: () -> Unit,
    viewModel: LockEraseViewModel = hiltViewModel(),
) {
    val state by viewModel.state.collectAsStateWithLifecycle()
    ForgotPinContent(
        state = state,
        onCancel = onCancel,
        onErase = viewModel::eraseEverything,
    )
}

@Composable
internal fun ForgotPinContent(
    state: EraseState,
    onCancel: () -> Unit,
    onErase: () -> Unit,
) {
    var typed by remember { mutableStateOf("") }
    var mismatch by remember { mutableStateOf(false) }

    Surface(modifier = Modifier.fillMaxSize()) {
        Column(
            modifier = Modifier
                .fillMaxSize()
                .verticalScroll(rememberScrollState())
                .padding(24.dp),
            verticalArrangement = Arrangement.Center,
            horizontalAlignment = Alignment.Start,
        ) {
            Text("There is no way to reset your PIN", style = MaterialTheme.typography.headlineMedium)

            Spacer(Modifier.height(16.dp))

            Text(
                "We cannot reset it for you, and there is no recovery code. That is " +
                    "deliberate: anything that could let us back in could let somebody " +
                    "else in too.",
                style = MaterialTheme.typography.bodyLarge,
            )

            Spacer(Modifier.height(12.dp))

            Text(
                "The only way past this screen is to erase everything you have recorded " +
                    "in this app and start again. This does not unlock anything and it " +
                    "does not bring anything back.",
                style = MaterialTheme.typography.bodyLarge,
            )

            Spacer(Modifier.height(12.dp))

            Text(
                "Anyone holding this phone could already do the same from Android's own " +
                    "settings, so this is that same erase and not an extra risk. Nothing " +
                    "is backed up anywhere, so there is no copy to restore either way.",
                style = MaterialTheme.typography.bodyMedium,
                color = MaterialTheme.colorScheme.onSurfaceVariant,
            )

            Spacer(Modifier.height(24.dp))

            when (state) {
                EraseState.DONE -> Text(
                    "Everything has been erased and the lock is off. You can start again.",
                    style = MaterialTheme.typography.bodyLarge,
                    modifier = Modifier.semantics { liveRegion = LiveRegionMode.Polite },
                )

                EraseState.FAILED -> Text(
                    "Something went wrong and nothing was erased. Your records are intact.",
                    style = MaterialTheme.typography.bodyLarge,
                    color = MaterialTheme.colorScheme.error,
                    modifier = Modifier.semantics { liveRegion = LiveRegionMode.Polite },
                )

                else -> {
                    Text("Type $CONFIRM_WORD to confirm.", style = MaterialTheme.typography.bodyMedium)
                    Spacer(Modifier.height(8.dp))
                    OutlinedTextField(
                        value = typed,
                        onValueChange = { typed = it; mismatch = false },
                        singleLine = true,
                        enabled = state != EraseState.ERASING,
                        isError = mismatch,
                        label = { Text(CONFIRM_WORD) },
                        keyboardOptions = KeyboardOptions(
                            keyboardType = KeyboardType.Text,
                            capitalization = KeyboardCapitalization.Characters,
                            imeAction = ImeAction.Done,
                        ),
                        modifier = Modifier.fillMaxWidth(),
                    )
                    if (mismatch) {
                        Text(
                            "Type $CONFIRM_WORD exactly to confirm.",
                            style = MaterialTheme.typography.bodySmall,
                            color = MaterialTheme.colorScheme.error,
                            modifier = Modifier.semantics { liveRegion = LiveRegionMode.Polite },
                        )
                    }

                    Spacer(Modifier.height(16.dp))

                    Button(
                        // Deliberately always enabled: a disabled button tells a
                        // screen-reader user nothing about why.
                        onClick = {
                            if (typed.trim().equals(CONFIRM_WORD, ignoreCase = true)) onErase() else mismatch = true
                        },
                        enabled = state != EraseState.ERASING,
                        colors = ButtonDefaults.buttonColors(
                            containerColor = MaterialTheme.colorScheme.error,
                            contentColor = MaterialTheme.colorScheme.onError,
                        ),
                        modifier = Modifier.fillMaxWidth(),
                    ) {
                        Text("Erase everything and start over")
                    }
                }
            }

            Spacer(Modifier.height(8.dp))

            TextButton(onClick = onCancel, modifier = Modifier.fillMaxWidth()) {
                Text(if (state == EraseState.DONE) "Continue" else "Go back")
            }
        }
    }
}

private const val CONFIRM_WORD = "ERASE"

@Preview(name = "Forgot PIN · light", showBackground = true, heightDp = 900)
@Preview(
    name = "Forgot PIN · dark",
    showBackground = true,
    heightDp = 900,
    uiMode = Configuration.UI_MODE_NIGHT_YES,
)
@Preview(name = "Forgot PIN · font 2.0", showBackground = true, heightDp = 1600, fontScale = 2.0f)
@Composable
private fun ForgotPinPreview() {
    PeriodTheme { ForgotPinContent(state = EraseState.IDLE, onCancel = {}, onErase = {}) }
}
