package ru.durakscore.app

import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.text.KeyboardActions
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.OutlinedTextFieldDefaults
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.focus.FocusDirection
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.platform.LocalFocusManager
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.input.ImeAction
import androidx.compose.ui.text.input.KeyboardType
import androidx.compose.ui.text.input.PasswordVisualTransformation
import androidx.compose.ui.text.input.VisualTransformation
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp


@Composable
fun AuthScreen(
    onAuthSuccess: (DurakSession) -> Unit
) {

    val focusManager =
        LocalFocusManager.current

    var isRegisterMode by remember {
        mutableStateOf(false)
    }

    var name by remember {
        mutableStateOf("")
    }

    var email by remember {
        mutableStateOf("")
    }

    var password by remember {
        mutableStateOf("")
    }

    var confirmPassword by remember {
        mutableStateOf("")
    }

    var showPassword by remember {
        mutableStateOf(false)
    }

    var isLoading by remember {
        mutableStateOf(false)
    }

    var errorText by remember {
        mutableStateOf<String?>(null)
    }


    fun clearError() {
        errorText =
            null
    }


    fun login() {

        if (
            isLoading
        ) {
            return
        }

        val cleanEmail =
            email.trim()

        if (
            cleanEmail.isBlank()
        ) {
            errorText =
                "Введите email"

            return
        }

        if (
            password.isBlank()
        ) {
            errorText =
                "Введите пароль"

            return
        }

        focusManager
            .clearFocus()

        isLoading =
            true

        errorText =
            null

        DurakServerApi.login(
            email =
                cleanEmail,
            password =
                password,
            onSuccess = {
                    session ->

                isLoading =
                    false

                onAuthSuccess(
                    session
                )
            },
            onError = {
                    message ->

                isLoading =
                    false

                errorText =
                    message.ifBlank {
                        "Не удалось выполнить вход"
                    }
            }
        )
    }


    fun register() {

        if (
            isLoading
        ) {
            return
        }

        val cleanName =
            name.trim()

        val cleanEmail =
            email.trim()

        when {

            cleanName.isBlank() -> {

                errorText =
                    "Введите имя"

                return
            }

            cleanEmail.isBlank() -> {

                errorText =
                    "Введите email"

                return
            }

            password.length < 8 -> {

                errorText =
                    "Пароль должен содержать минимум 8 символов"

                return
            }

            password !=
                confirmPassword -> {

                errorText =
                    "Пароли не совпадают"

                return
            }
        }

        focusManager
            .clearFocus()

        isLoading =
            true

        errorText =
            null

        DurakServerApi.register(
            name =
                cleanName,
            email =
                cleanEmail,
            password =
                password,
            onSuccess = {
                    session ->

                isLoading =
                    false

                onAuthSuccess(
                    session
                )
            },
            onError = {
                    message ->

                isLoading =
                    false

                errorText =
                    message.ifBlank {
                        "Не удалось создать аккаунт"
                    }
            }
        )
    }


    PokerScreen {

        Spacer(
            modifier =
                Modifier.height(
                    34.dp
                )
        )

        Text(
            text =
                "♠   ♥   ♦   ♣",
            color =
                PokerPalette.Gold,
            fontSize =
                20.sp,
            fontWeight =
                FontWeight.Bold,
            modifier =
                Modifier.align(
                    Alignment.CenterHorizontally
                )
        )

        Spacer(
            modifier =
                Modifier.height(
                    18.dp
                )
        )

        Text(
            text =
                "ДУРАК",
            color =
                PokerPalette.TextPrimary,
            fontSize =
                48.sp,
            fontWeight =
                FontWeight.ExtraBold,
            modifier =
                Modifier.align(
                    Alignment.CenterHorizontally
                )
        )

        Spacer(
            modifier =
                Modifier.height(
                    6.dp
                )
        )

        Text(
            text =
                if (
                    isRegisterMode
                ) {
                    "Регистрация за столом"
                } else {
                    "Вход за игровой стол"
                },
            color =
                PokerPalette.TextSecondary,
            fontSize =
                18.sp,
            modifier =
                Modifier.align(
                    Alignment.CenterHorizontally
                )
        )

        Spacer(
            modifier =
                Modifier.height(
                    28.dp
                )
        )

        PokerPanel {

            Text(
                text =
                    if (
                        isRegisterMode
                    ) {
                        "Создать аккаунт"
                    } else {
                        "Войти"
                    },
                color =
                    PokerPalette.Gold,
                fontSize =
                    22.sp,
                fontWeight =
                    FontWeight.Bold
            )

            Spacer(
                modifier =
                    Modifier.height(
                        18.dp
                    )
            )

            if (
                isRegisterMode
            ) {

                PokerAuthTextField(
                    value =
                        name,
                    onValueChange = {
                        name =
                            it
                        clearError()
                    },
                    label =
                        "Имя",
                    keyboardType =
                        KeyboardType.Text,
                    imeAction =
                        ImeAction.Next,
                    onNext = {
                        focusManager
                            .moveFocus(
                                FocusDirection.Down
                            )
                    }
                )

                Spacer(
                    modifier =
                        Modifier.height(
                            12.dp
                        )
                )
            }

            PokerAuthTextField(
                value =
                    email,
                onValueChange = {
                    email =
                        it
                    clearError()
                },
                label =
                    "Email",
                keyboardType =
                    KeyboardType.Email,
                imeAction =
                    ImeAction.Next,
                onNext = {
                    focusManager
                        .moveFocus(
                            FocusDirection.Down
                        )
                }
            )

            Spacer(
                modifier =
                    Modifier.height(
                        12.dp
                    )
            )

            PokerAuthTextField(
                value =
                    password,
                onValueChange = {
                    password =
                        it
                    clearError()
                },
                label =
                    "Пароль",
                keyboardType =
                    KeyboardType.Password,
                imeAction =
                    if (
                        isRegisterMode
                    ) {
                        ImeAction.Next
                    } else {
                        ImeAction.Done
                    },
                isPassword =
                    true,
                showPassword =
                    showPassword,
                onNext = {
                    if (
                        isRegisterMode
                    ) {
                        focusManager
                            .moveFocus(
                                FocusDirection.Down
                            )
                    } else {
                        login()
                    }
                }
            )

            if (
                isRegisterMode
            ) {

                Spacer(
                    modifier =
                        Modifier.height(
                            12.dp
                        )
                )

                PokerAuthTextField(
                    value =
                        confirmPassword,
                    onValueChange = {
                        confirmPassword =
                            it
                        clearError()
                    },
                    label =
                        "Повторите пароль",
                    keyboardType =
                        KeyboardType.Password,
                    imeAction =
                        ImeAction.Done,
                    isPassword =
                        true,
                    showPassword =
                        showPassword,
                    onNext = {
                        register()
                    }
                )
            }

            TextButton(
                onClick = {
                    showPassword =
                        !showPassword
                },
                enabled =
                    !isLoading
            ) {

                Text(
                    text =
                        if (
                            showPassword
                        ) {
                            "Скрыть пароль"
                        } else {
                            "Показать пароль"
                        },
                    color =
                        PokerPalette.TextSecondary
                )
            }

            if (
                errorText !=
                null
            ) {

                Spacer(
                    modifier =
                        Modifier.height(
                            6.dp
                        )
                )

                PokerAuthError(
                    text =
                        errorText!!
                )
            }

            Spacer(
                modifier =
                    Modifier.height(
                        18.dp
                    )
            )

            if (
                isLoading
            ) {

                CircularProgressIndicator(
                    color =
                        PokerPalette.Gold,
                    modifier =
                        Modifier.align(
                            Alignment.CenterHorizontally
                        )
                )

                Spacer(
                    modifier =
                        Modifier.height(
                            10.dp
                        )
                )

                Text(
                    text =
                        if (
                            isRegisterMode
                        ) {
                            "Создаю аккаунт..."
                        } else {
                            "Выполняю вход..."
                        },
                    color =
                        PokerPalette.TextSecondary,
                    modifier =
                        Modifier.align(
                            Alignment.CenterHorizontally
                        )
                )

            } else {

                PokerPrimaryButton(
                    text =
                        if (
                            isRegisterMode
                        ) {
                            "Зарегистрироваться"
                        } else {
                            "Войти"
                        },
                    onClick = {
                        if (
                            isRegisterMode
                        ) {
                            register()
                        } else {
                            login()
                        }
                    }
                )
            }

            Spacer(
                modifier =
                    Modifier.height(
                        12.dp
                    )
            )

            PokerSecondaryButton(
                text =
                    if (
                        isRegisterMode
                    ) {
                        "У меня уже есть аккаунт"
                    } else {
                        "Нет аккаунта? Регистрация"
                    },
                onClick = {

                    if (
                        !isLoading
                    ) {

                        isRegisterMode =
                            !isRegisterMode

                        errorText =
                            null

                        password =
                            ""

                        confirmPassword =
                            ""

                        showPassword =
                            false
                    }
                },
                enabled =
                    !isLoading
            )
        }

        Spacer(
            modifier =
                Modifier.height(
                    22.dp
                )
        )

        Text(
            text =
                if (
                    isRegisterMode
                ) {
                    "После регистрации администратор должен подтвердить доступ."
                } else {
                    "Доступ только для участников игры."
                },
            color =
                PokerPalette.TextSecondary,
            fontSize =
                14.sp,
            modifier =
                Modifier.align(
                    Alignment.CenterHorizontally
                )
        )

        Spacer(
            modifier =
                Modifier.height(
                    24.dp
                )
        )
    }
}


@Composable
private fun PokerAuthTextField(
    value: String,
    onValueChange: (String) -> Unit,
    label: String,
    keyboardType: KeyboardType,
    imeAction: ImeAction,
    onNext: () -> Unit,
    isPassword: Boolean = false,
    showPassword: Boolean = false
) {

    OutlinedTextField(
        value =
            value,
        onValueChange =
            onValueChange,
        modifier =
            Modifier.fillMaxWidth(),
        label = {
            Text(
                label
            )
        },
        singleLine =
            true,
        shape =
            RoundedCornerShape(
                16.dp
            ),
        keyboardOptions =
            KeyboardOptions(
                keyboardType =
                    keyboardType,
                imeAction =
                    imeAction
            ),
        keyboardActions =
            KeyboardActions(
                onNext = {
                    onNext()
                },
                onDone = {
                    onNext()
                }
            ),
        visualTransformation =
            if (
                isPassword &&
                !showPassword
            ) {
                PasswordVisualTransformation()
            } else {
                VisualTransformation.None
            },
        colors =
            OutlinedTextFieldDefaults.colors(
                focusedTextColor =
                    PokerPalette.TextPrimary,
                unfocusedTextColor =
                    PokerPalette.TextPrimary,
                focusedBorderColor =
                    PokerPalette.Gold,
                unfocusedBorderColor =
                    PokerPalette.GoldDark,
                focusedLabelColor =
                    PokerPalette.Gold,
                unfocusedLabelColor =
                    PokerPalette.TextSecondary,
                cursorColor =
                    PokerPalette.Gold,
                focusedContainerColor =
                    Color.Transparent,
                unfocusedContainerColor =
                    Color.Transparent
            )
    )
}


@Composable
private fun PokerAuthError(
    text: String
) {

    PokerPanel {

        Text(
            text =
                "Ошибка",
            color =
                PokerPalette.Danger,
            fontWeight =
                FontWeight.Bold,
            fontSize =
                16.sp
        )

        Spacer(
            modifier =
                Modifier.height(
                    5.dp
                )
        )

        Text(
            text =
                text,
            color =
                PokerPalette.TextPrimary,
            fontSize =
                15.sp
        )
    }
}
