package moe.lava.neon.ui.screens

import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.safeContentPadding
import androidx.compose.material3.Button
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.text.input.PasswordVisualTransformation
import androidx.compose.ui.text.input.VisualTransformation
import androidx.compose.ui.unit.dp
import androidx.lifecycle.ViewModel
import co.touchlab.kermit.Logger
import kotlinx.coroutines.launch
import moe.lava.neon.core.repository.AuthRepository
import moe.lava.neon.core.repository.AuthResponse
import moe.lava.neon.resources.Res
import moe.lava.neon.resources.visibility
import moe.lava.neon.resources.visibility_off
import org.jetbrains.compose.resources.painterResource
import org.koin.compose.viewmodel.koinViewModel

@Composable
fun Login(
    onSuccess: () -> Unit,
) {
    val viewModel: LoginViewModel = koinViewModel()
    val scope = rememberCoroutineScope()

    Column(
        modifier = Modifier
//            .background(MaterialTheme.colorScheme.primaryContainer)
            .safeContentPadding()
            .fillMaxSize()
    ) {
        Text("Login!")
        Spacer(Modifier.height(4.dp))

        var email by rememberSaveable { mutableStateOf("") }
        var password by rememberSaveable { mutableStateOf("") }
        var passwordVisible by rememberSaveable { mutableStateOf(false) }
        var failMessage by rememberSaveable { mutableStateOf<String?>(null) }
        var loginEnabled by rememberSaveable { mutableStateOf(true) }

        OutlinedTextField(
            value = email,
            onValueChange = { email = it },
            label = { Text("Enter email") },
        )
        // TODO: Switch to SecureTextField
        OutlinedTextField(
            value = password,
            onValueChange = { password = it },
            label = { Text("Enter password") },
            visualTransformation = if (passwordVisible) VisualTransformation.None else PasswordVisualTransformation(),
            trailingIcon = {
                val image = if (passwordVisible) {
                    Res.drawable.visibility
                } else {
                    Res.drawable.visibility_off
                }

                val description = if (passwordVisible) "Hide password" else "Show password"

                IconButton(onClick = { passwordVisible = !passwordVisible }) {
                    Icon(painter = painterResource(image), description)
                }
            }
        )
        if (failMessage != null) {
            Text("Login failed (${failMessage})", color = Color.Red)
        }
        Spacer(Modifier.height(4.dp))

        fun login() {
            loginEnabled = false
            scope.launch {
                val res = viewModel.login(email, password)
                loginEnabled = true
                when (res) {
                    is LoginViewModel.LoginResult.Failed -> { failMessage = res.message }
                    LoginViewModel.LoginResult.Success -> onSuccess()
                }
            }
        }

        Button(
            enabled = loginEnabled,
            onClick = {
                failMessage = null
                loginEnabled = false
                login()
            }
        ) {
            Text("Submit")
        }
    }
}

class LoginViewModel(
    private val auth: AuthRepository
) : ViewModel() {
    private val logger = Logger.withTag("neon.ui.screens/login")

    sealed interface LoginResult {
        data class Failed(val message: String) : LoginResult
        // TODO
//        data class MFARequested() : LoginResult
        data object Success : LoginResult
    }

    suspend fun login(email: String, password: String): LoginResult {
        return when (val res = auth.login(email, password)) {
            is AuthResponse.Success -> LoginResult.Success
            is AuthResponse.Failed -> {
                val e = res.error
                logger.e(e) { "Login failed" }
                LoginResult.Failed(e.toString())
            }
        }
    }
}
