package dev.inmo.postssystem.client.fsm.ui

import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import dev.inmo.jsuikit.elements.*
import dev.inmo.jsuikit.modifiers.*
import dev.inmo.jsuikit.utils.Attrs
import dev.inmo.postssystem.client.ui.fsm.*
import dev.inmo.postssystem.features.auth.client.ui.*
import dev.inmo.micro_utils.coroutines.launchSafelyWithoutExceptions
import dev.inmo.micro_utils.coroutines.subscribeSafelyWithoutExceptions
import dev.inmo.micro_utils.fsm.common.StatesMachine
import dev.inmo.postssystem.client.utils.renderComposableAndLinkToContext
import kotlinx.browser.document
import kotlinx.coroutines.*
import kotlinx.dom.*
import org.jetbrains.compose.web.attributes.InputType
import org.jetbrains.compose.web.dom.*
import org.jetbrains.compose.web.dom.Text
import org.w3c.dom.*

class AuthView(
    private val viewModel: AuthUIViewModel,
    private val uiScope: CoroutineScope
) : JSView<AuthUIFSMState>() {

    override suspend fun StatesMachine<in UIFSMState>.safeHandleState(
        htmlElement: HTMLElement,
        state: AuthUIFSMState
    ): UIFSMState? {
        val completion = CompletableDeferred<UIFSMState?>()

        val usernameState = mutableStateOf("")
        val passwordState = mutableStateOf("")
        val disabled = mutableStateOf(true)
        val errorText = mutableStateOf<String?>(null)

        val root = htmlElement.appendElement("div") {}
        val composition = renderComposableAndLinkToContext(root) {
            val authBtnDisabled = usernameState.value.isBlank() || passwordState.value.isBlank()

            Flex(
                UIKitFlex.Alignment.Horizontal.Center
            ) {
                Card(
                    Attrs(UIKitText.Alignment.Horizontal.Center),
                    bodyAttrs = Attrs(UIKitWidth.Fixed.Medium),
                ) {
                    CardTitle { Text("Log in") }

                    if (errorText.value != null) {
                        CardBadge(Attrs(UIKitLabel.Error)) {
                            Text(errorText.value.toString())
                        }
                    }

                    TextField(
                        InputType.Text,
                        usernameState,
                        disabled,
                        "Username",
                    )
                    TextField(
                        InputType.Password,
                        passwordState,
                        disabled,
                        "Password"
                    )

                    DefaultButton("Authorise", UIKitButton.Type.Primary, UIKitMargin.Small, disabled = authBtnDisabled) {
                        it.nativeEvent.preventDefault()
                        val serverUrl = document.location ?.run { "$hostname:$port" }
                        if (serverUrl != null) {
                            uiScope.launchSafelyWithoutExceptions { viewModel.initAuth(serverUrl, usernameState.value, passwordState.value) }
                        }
                    }
                }
            }
        }

        val viewJob = viewModel.currentState.subscribeSafelyWithoutExceptions(uiScope) {
            when (it) {
                is InitAuthUIState -> {
                    disabled.value = false

                    errorText.value = when (it.showError) {
                        ServerUnavailableAuthUIError -> "Server unavailable"
                        AuthIncorrectAuthUIError -> {
                            passwordState.value = ""
                            "Username or password is incorrect"
                        }
                        null -> null
                    }
                }
                LoadingAuthUIState -> {
                    disabled.value = true
                    errorText.value = null
                }
                AuthorizedAuthUIState -> {
                    completion.complete(state.from)
                }
            }
        }
        return completion.await().also {
            composition.dispose()
            viewJob.cancel()
        }
    }
}