package llc.arma.ble.app.ui.screen.inspection.host.view.table

import androidx.activity.compose.BackHandler
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
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.layout.widthIn
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.items
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material.ExperimentalMaterialApi
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.rounded.Add
import androidx.compose.material.icons.rounded.ArrowBack
import androidx.compose.material.icons.rounded.RemoveCircleOutline
import androidx.compose.material3.Checkbox
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.material3.TopAppBar
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.rememberCoroutineScope
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.Dialog
import androidx.hilt.navigation.compose.hiltViewModel
import kotlinx.coroutines.flow.launchIn
import kotlinx.coroutines.flow.onEach
import kotlinx.coroutines.launch
import llc.arma.ble.app.ui.common.rememberBottomDialogState
import llc.arma.ble.app.ui.screen.ble.BleItem
import llc.arma.ble.domain.model.BleInfo
import llc.arma.ble.domain.model.BleName

@OptIn(ExperimentalMaterial3Api::class, ExperimentalMaterialApi::class)
@Composable
fun BleTableEditScreen(
    serial: String,
    onEvent: (event: BleTableEditContract.Effect.Navigation) -> Unit
) {

    val viewModel = hiltViewModel<BleTableEditViewModel>()
    val state = viewModel.viewState.value

    LaunchedEffect(Unit) {
        viewModel.effect.onEach {
            when(it){
                is BleTableEditContract.Effect.Navigation -> onEvent(it)
            }
        }.launchIn(this)
    }

    LaunchedEffect(key1 = serial) {
        viewModel.setEvent(BleTableEditContract.Event.OnStart(serial))
    }

    var showSelector by remember {
        mutableStateOf(false)
    }

    BackHandler(showSelector) {
        showSelector = false
    }

    val scope = rememberCoroutineScope()
    val bottomDialog = rememberBottomDialogState()

    BackHandler(bottomDialog.sheetState?.isVisible == true) {
        scope.launch {
            bottomDialog.hide()
        }

    }

    Column(
        modifier = Modifier.fillMaxSize()
    ) {

        TopAppBar(
            navigationIcon = {
                IconButton(onClick = {
                    if(showSelector){
                        showSelector = false
                    } else {
                        onEvent(BleTableEditContract.Effect.Navigation.NavigateUp)
                    }
                }) {
                    Icon(
                        imageVector = Icons.Rounded.ArrowBack,
                        contentDescription = null
                    )
                }
            },
            title = {
                Text(
                    modifier = Modifier.weight(1f),
                    text = if(showSelector){
                        "Выберите BLE"
                    } else {
                        "Таблица BLE ID"
                    },
                    style = MaterialTheme.typography.titleLarge
                )
            },
            actions = {
                if(showSelector.not()){
                    IconButton(
                        enabled = state is BleTableEditContract.State.Display,
                        onClick = { showSelector=true }
                    ) {
                        Icon(
                            imageVector = Icons.Rounded.Add,
                            contentDescription = null
                        )
                    }
                }
            }

        )

        if(state is BleTableEditContract.State.Loading){

            Box(
                contentAlignment = Alignment.Center,
                modifier = Modifier.fillMaxSize()
            ){

                CircularProgressIndicator()

            }

        }

        if(state is BleTableEditContract.State.Error){

            Box(
                contentAlignment = Alignment.Center,
                modifier = Modifier.fillMaxSize()
            ){

                Column(
                    horizontalAlignment = Alignment.CenterHorizontally,
                    verticalArrangement = Arrangement.spacedBy(8.dp),
                    modifier = Modifier.widthIn(max = 200.dp)
                ) {

                    Text(
                        textAlign = TextAlign.Center,
                        text = "Во время загрузки произошла ошибка",
                    )

                    Surface(
                        modifier = Modifier
                            .padding(8.dp)
                            .height(50.dp),
                        shape = CircleShape,
                        color = MaterialTheme.colorScheme.primary,
                        onClick = {
                            viewModel.setEvent(BleTableEditContract.Event.OnStart(serial))
                        }
                    ) {

                        Box(modifier = Modifier) {

                            Text(
                                modifier = Modifier.align(Alignment.Center),
                                color = MaterialTheme.colorScheme.onPrimary,
                                style = MaterialTheme.typography.labelLarge,
                                text = "Повторить"
                            )

                        }

                    }

                }

            }

        }

        if (state is BleTableEditContract.State.Display) {

            if(showSelector) {

                BleSelectorScreen(
                    saved = state.savedBleTable.map { it.serial },
                    selected = state.newTable.map { it.serial },
                    bleList = state.bleAround,
                    onClose = {
                        showSelector = false
                    }
                ) {
                    viewModel.setEvent(
                        BleTableEditContract.Event.OnAddBle(
                            BleName(
                                serial = it.serial,
                                name = it.name
                            )
                        )
                    )
                }

            } else {

                var editBle by remember {
                    mutableStateOf<BleName?>(null)
                }

                LazyColumn(
                    modifier = Modifier
                        .weight(1f)
                        .padding(horizontal = 12.dp)
                ) {

                    val savedBleSerials =  state.savedBleTable.map { it.serial }
                    val newBle = state.newTable.filterNot { ble -> savedBleSerials.contains(ble.serial) }

                    if (newBle.isNotEmpty()) {

                        item {
                            Text(
                                style = MaterialTheme.typography.titleLarge,
                                textAlign = TextAlign.Center,
                                text = "Новые BLE",
                            )
                        }

                        items(items = newBle) {
                            SelectBleItem(
                                ble = it,
                                onClick = {
                                    editBle = it
                                    viewModel.setEvent(BleTableEditContract.Event.OnAddBle(it))
                                }
                            ) {
                                viewModel.setEvent(BleTableEditContract.Event.OnAddBle(it))
                            }
                        }

                    }

                    if (state.savedBleTable.isNotEmpty()) {

                        item {
                            Text(
                                style = MaterialTheme.typography.titleLarge,
                                textAlign = TextAlign.Center,
                                text = "Сохраненные BLE",
                            )
                        }

                        items(items = state.savedBleTable) { ble ->
                            SavedBleItem(
                                checked = state.newTable.any { it.serial == ble.serial},
                                ble = ble
                            ){
                                viewModel.setEvent(BleTableEditContract.Event.OnAddBle(ble))
                            }
                        }

                    }

                }

                Surface(
                    modifier = Modifier
                        .fillMaxWidth()
                        .padding(8.dp)
                        .height(50.dp),
                    shape = CircleShape,
                    color = MaterialTheme.colorScheme.primaryContainer,
                    onClick = {
                        viewModel.setEvent(BleTableEditContract.Event.OnWritePreview)
                    }
                ) {

                    Box(modifier = Modifier.fillMaxSize()) {

                        Text(
                            modifier = Modifier.align(Alignment.Center),
                            color = MaterialTheme.colorScheme.background,
                            style = MaterialTheme.typography.labelLarge,
                            text = "Записать"
                        )

                    }

                }

                if(editBle != null){

                    Dialog(
                        onDismissRequest = {
                            viewModel.setEvent(BleTableEditContract.Event.OnAddBle(ble = editBle!!.copy()))
                            editBle = null
                        }
                    ) {

                        Surface(
                            shape = RoundedCornerShape(24.dp)
                        ) {

                            Column(
                                verticalArrangement = Arrangement.spacedBy(12.dp),
                                modifier = Modifier.padding(24.dp)
                            ) {

                                var name by remember(editBle) {
                                    mutableStateOf(editBle?.name ?: "")
                                }

                                Text(
                                    style = MaterialTheme.typography.titleLarge,
                                    text = "Введите название"
                                )
                                
                                OutlinedTextField(
                                    value = name,
                                    singleLine = true,
                                    onValueChange = {
                                        name = it
                                    }
                                )

                                Surface(
                                    modifier = Modifier
                                        .fillMaxWidth()
                                        .height(50.dp),
                                    shape = CircleShape,
                                    color = MaterialTheme.colorScheme.primaryContainer,
                                    onClick = {
                                        viewModel.setEvent(
                                            BleTableEditContract.Event.OnAddBle(
                                                ble = editBle!!.copy(name = name)
                                            )
                                        )
                                        editBle = null
                                    }
                                ) {

                                    Box(modifier = Modifier.fillMaxSize()) {

                                        Text(
                                            modifier = Modifier.align(Alignment.Center),
                                            color = MaterialTheme.colorScheme.background,
                                            style = MaterialTheme.typography.labelLarge,
                                            text = "Сохранить"
                                        )

                                    }

                                }

                            }

                        }

                    }

                }

                LaunchedEffect(key1 = bottomDialog.sheetState?.isVisible) {
                    if (bottomDialog.sheetState?.isVisible?.not() == true) {
                        viewModel.setEvent(BleTableEditContract.Event.OnHideWritePreview)
                    }
                }

                LaunchedEffect(key1 = state.writeState) {

                    if (state.writeState == null) {
                        bottomDialog.hide()
                    } else {
                        bottomDialog.show {
                            Write(
                                state = state.writeState,
                                onEvent = {
                                    viewModel.setEvent(it)
                                }
                            )
                        }
                    }

                }

            }

        }

    }

}

@Composable
fun BleSelectorScreen(
    saved: List<String>,
    selected: List<String>,
    bleList: List<BleInfo>,
    onClose: () -> Unit,
    onAddBle: (BleInfo) -> Unit
) {

    Column(
        modifier = Modifier.fillMaxSize()
    ) {

        LazyColumn(
            modifier = Modifier.weight(1f)
        ) {

            items(items = bleList.filterNot { saved.contains(it.serial) }) { ble ->

                Row(
                    horizontalArrangement = Arrangement.spacedBy(8.dp),
                    verticalAlignment = Alignment.CenterVertically,
                    modifier = Modifier
                        .padding(horizontal = 8.dp)
                        .clickable {
                            onAddBle(ble)
                        }
                ) {

                    Checkbox(
                        checked = selected.any { it == ble.serial },
                        onCheckedChange = null
                    )

                    BleItem(ble = ble) {
                        onAddBle(ble)
                    }

                }

            }


        }

        Surface(
            modifier = Modifier
                .fillMaxWidth()
                .padding(8.dp)
                .height(50.dp),
            shape = CircleShape,
            color = MaterialTheme.colorScheme.primaryContainer,
            onClick = {
                onClose()
            }
        ) {

            Box(modifier = Modifier.fillMaxSize()) {

                Text(
                    modifier = Modifier.align(Alignment.Center),
                    color = MaterialTheme.colorScheme.background,
                    style = MaterialTheme.typography.labelLarge,
                    text = "Сохранить"
                )

            }

        }

    }
    
}

@Composable
fun SelectBleItem(
    ble: BleName,
    onClick: (() -> Unit)? = null,
    onRemove: (() -> Unit)? = null,
){

    Row(
        verticalAlignment = Alignment.CenterVertically,
        horizontalArrangement = Arrangement.spacedBy(12.dp),
        modifier = Modifier
            .fillMaxWidth()
            .clip(RoundedCornerShape(16.dp))
            .clickable { onClick?.invoke() }
            .padding(vertical = 8.dp, horizontal = 16.dp)

    ) {

        Column(
            modifier = Modifier.weight(1f)
        ) {

            Text(text = ble.name)

            Text(
                style = MaterialTheme.typography.bodyMedium,
                text = ble.serial
            )

        }

        onRemove?.let {

            IconButton(onClick = onRemove) {

                Icon(
                    imageVector = Icons.Rounded.RemoveCircleOutline,
                    contentDescription = null
                )

            }

        }

    }

}

@Composable
fun SavedBleItem(
    checked: Boolean,
    ble: BleName,
    onClick: () -> Unit
){

    Row(
        verticalAlignment = Alignment.CenterVertically,
        horizontalArrangement = Arrangement.SpaceBetween,
        modifier = Modifier
            .fillMaxWidth()
            .clip(RoundedCornerShape(16.dp))
            .clickable { onClick() }
            .padding(vertical = 8.dp, horizontal = 16.dp)
            .padding(end = 12.dp)
    ) {

        Column {

            Text(text = ble.name)
            Text(text = ble.serial)

        }

        Checkbox(checked = checked, onCheckedChange = null)

    }

}