package com.pixelized.biblib.ui.screen.home.detail

import android.content.Context
import androidx.activity.compose.BackHandler
import androidx.annotation.StringRes
import androidx.compose.foundation.layout.*
import androidx.compose.material.*
import androidx.compose.runtime.*
import androidx.compose.ui.Modifier
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalUriHandler
import androidx.compose.ui.res.stringResource
import androidx.compose.ui.unit.dp
import androidx.hilt.navigation.compose.hiltViewModel
import com.pixelized.biblib.R
import com.pixelized.biblib.ui.LocalSnackHostState
import com.pixelized.biblib.ui.composable.scaffold.LocalDetailBottomSheetState
import com.pixelized.biblib.ui.screen.home.profile.ProfileViewModel
import com.pixelized.biblib.ui.screen.home.profile.UserUio
import com.pixelized.biblib.ui.theme.color.ShadowPalette
import com.pixelized.biblib.utils.extention.bibLib
import kotlinx.coroutines.launch

@Stable
@Immutable
sealed class BookDetailUioErrorUio(
    @StringRes val message: Int,
    @StringRes val action: Int,
) {
    @Stable
    @Immutable
    class GetDetailInput(
        @StringRes message: Int,
        @StringRes action: Int,
        val bookId: Int,
    ) : BookDetailUioErrorUio(message, action)

    @Stable
    @Immutable
    class SendBookInput(
        @StringRes message: Int,
        @StringRes action: Int,
        val bookId: Int,
        val mail: String,
        val format: String,
    ) : BookDetailUioErrorUio(message, action)
}

@OptIn(ExperimentalMaterialApi::class)
@Composable
fun DetailScreen(
    detailViewModel: BookDetailViewModel = hiltViewModel(),
    profileViewModel: ProfileViewModel = hiltViewModel(),
    onAuthor: (String?, Int?) -> Unit,
    onSeries: (String?, Int?) -> Unit,
    bookId: Int? = null,
) {
    val detailState = LocalDetailBottomSheetState.current
    val snackBarHost = LocalSnackHostState.current
    val uriHandler = LocalUriHandler.current
    val context = LocalContext.current

    val scope = rememberCoroutineScope()
    val emailSheetState = rememberModalBottomSheetState(
        initialValue = ModalBottomSheetValue.Hidden,
        skipHalfExpanded = true,
    )

    when (val detail = detailViewModel.detail.value) {
        null -> EmptyDetail()
        else -> {
            val bibLibUrl = stringResource(id = R.string.detail_open_on_biblib_url, detail.id)

            ModalBottomSheetLayout(
                modifier = Modifier.fillMaxSize(),
                sheetState = emailSheetState,
                sheetShape = MaterialTheme.bibLib.shapes.sheet,
                scrimColor = ShadowPalette.scrim,
                sheetContent = {
                    DetailScreenSendOption(
                        modifier = Modifier
                            .navigationBarsPadding()
                            .padding(bottom = 16.dp),
                        emails = profileViewModel.mails,
                        onHelp = { uri ->
                            uriHandler.openUri(uri)
                        },
                        onSend = { mail, format ->
                            scope.launch { emailSheetState.hide() }
                            detailViewModel.send(bookId = detail.id, email = mail, format = format)
                        }
                    )
                },
                content = {
                    if (detailState.bottomSheetState.isVisible) {
                        DetailScreenContent(
                            book = detail,
                            onOpenOnBibLib = {
                                uriHandler.openUri(bibLibUrl)
                            },
                            onAuthor = { onAuthor(it.name, it.id) },
                            onSeries = { onSeries(it.name, it.id) },
                            onSend = {
                                scope.launch {
                                    send(
                                        context = context,
                                        profileViewModel = profileViewModel,
                                        snackBarHost = snackBarHost,
                                        emailSheetState = emailSheetState,
                                        user = profileViewModel.user
                                    )
                                }
                            }
                        )
                        DetailScreenSendLoader(
                            loadingVisibility = detailViewModel.sendStatus,
                            successVisibility = detailViewModel.sendingFlow,
                        )
                    } else {
                        EmptyDetail()
                    }
                },
            )
        }
    }

    if (detailState.bottomSheetState.isVisible) {
        LaunchedEffect(key1 = "DetailScreen$bookId") {
            launch {
                detailViewModel.error.collect {
                    val result = snackBarHost.showSnackbar(
                        message = context.getString(it.message),
                        actionLabel = context.getString(it.action),
                    )
                    if (result == SnackbarResult.ActionPerformed) {
                        when (it) {
                            is BookDetailUioErrorUio.GetDetailInput -> detailViewModel.getDetail(
                                bookId = it.bookId
                            )
                            is BookDetailUioErrorUio.SendBookInput -> detailViewModel.send(
                                bookId = it.bookId,
                                email = it.mail,
                                format = it.format,
                            )
                        }
                    }
                }
            }
            launch {
                bookId?.let { detailViewModel.getDetail(it) }
            }
            launch {
                emailSheetState.hide()
            }
        }

        BackHandler(emailSheetState.isVisible) {
            scope.launch {
                emailSheetState.hide()
            }
        }
    }
}

@OptIn(ExperimentalMaterialApi::class)
private suspend fun send(
    context: Context,
    profileViewModel: ProfileViewModel,
    snackBarHost: SnackbarHostState,
    emailSheetState: ModalBottomSheetState,
    user: State<UserUio?>,
) {
    if (user.value?.amazonEmails?.isNotEmpty() == true) {
        emailSheetState.show()
    } else {
        val result = snackBarHost.showSnackbar(
            message = context.getString(R.string.error_send_no_amazon_email_message),
            actionLabel = context.getString(R.string.error_send_no_amazon_email_action),
            duration = SnackbarDuration.Indefinite,
        )
        if (result == SnackbarResult.ActionPerformed) {
            profileViewModel.updateUser()
            send(
                context = context,
                profileViewModel = profileViewModel,
                snackBarHost = snackBarHost,
                emailSheetState = emailSheetState,
                user = user
            )
        }
    }
}

@Composable
private fun EmptyDetail(
    modifier: Modifier = Modifier,
) = Box(
    modifier = modifier.fillMaxSize()
)