package io.nexilis.alpha.ui.components

import android.Manifest
import android.content.Context
import android.net.Uri
import android.os.Bundle
import android.os.Parcelable
import android.provider.OpenableColumns
import android.widget.Toast
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.Row
import androidx.compose.foundation.layout.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.text.KeyboardOptions
import androidx.compose.material.icons.Icons
import androidx.compose.material.icons.automirrored.filled.Send
import androidx.compose.material.icons.filled.Add
import androidx.compose.material.icons.filled.AttachFile
import androidx.compose.material.icons.filled.Camera
import androidx.compose.material.icons.filled.Headset
import androidx.compose.material.icons.filled.Image
import androidx.compose.material.icons.filled.LocationOn
import androidx.compose.material.icons.filled.Person
import androidx.compose.material3.ExperimentalMaterial3Api
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.Text
import androidx.compose.material3.TextField
import androidx.compose.material3.TextFieldDefaults
import androidx.compose.material3.TooltipDefaults
import androidx.compose.runtime.Composable
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.saveable.rememberSaveable
import androidx.compose.runtime.setValue
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.graphics.Color
import androidx.compose.ui.graphics.graphicsLayer
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.platform.LocalSoftwareKeyboardController
import androidx.compose.ui.res.painterResource
import androidx.compose.ui.text.TextRange
import androidx.compose.ui.text.input.KeyboardCapitalization
import androidx.compose.ui.text.input.TextFieldValue
import androidx.compose.ui.unit.dp
import androidx.compose.ui.window.Popup
import androidx.core.content.FileProvider
import androidx.core.net.toUri
import androidx.hilt.navigation.compose.hiltViewModel
import androidx.navigation.NavHostController
import androidx.navigation.NavType
import coil.compose.AsyncImage
import coil.request.ImageRequest
import io.nexilis.alpha.BuildConfig
import io.nexilis.alpha.R
import io.nexilis.service.core.BlueSky
import io.nexilis.service.core.DarkLimeGreen
import io.nexilis.service.core.Orange
import io.nexilis.service.core.Purple
import io.nexilis.service.core.createFile
import io.nexilis.service.core.getMimeType
import io.nexilis.service.core.getSharedPreferences
import io.nexilis.service.data.entities.Message
import io.nexilis.service.data.viewmodels.MessageViewModel
import kotlinx.parcelize.Parcelize
import kotlinx.serialization.KSerializer
import kotlinx.serialization.Serializable
import kotlinx.serialization.descriptors.PrimitiveKind
import kotlinx.serialization.descriptors.PrimitiveSerialDescriptor
import kotlinx.serialization.descriptors.SerialDescriptor
import kotlinx.serialization.encoding.Decoder
import kotlinx.serialization.encoding.Encoder
import kotlinx.serialization.json.Json

@OptIn(ExperimentalMaterial3Api::class)
@Composable
fun Attachments(modifier: Modifier, onAttachment: (List<Uri>) -> Unit) {
    val keyboardController = LocalSoftwareKeyboardController.current
    val positionProvider = TooltipDefaults.rememberPlainTooltipPositionProvider()
    var isOpenMenu by remember {
        mutableStateOf(false)
    }
    val context = LocalContext.current
    var tempUri = Uri.EMPTY
    IconButton(onClick = {
        keyboardController?.hide()
        isOpenMenu = !isOpenMenu
    }
    ) {
        Icon(
            imageVector = Icons.Default.Add,
            contentDescription = "",
            tint = MaterialTheme.colorScheme.primary
        )
    }
    if (isOpenMenu) {
        Popup(popupPositionProvider = positionProvider, onDismissRequest = { isOpenMenu = false }) {
            Box(modifier = modifier) {
                Row(Modifier.align(Alignment.Center)) {
                    var mimeType = arrayOf(
                        "doc/*",
                        "docx/*",
                        "application/*"
                    )
                    val launcherFiles =
                        rememberLauncherForActivityResult(ActivityResultContracts.OpenMultipleDocuments()) {
                            onAttachment(it)
                            isOpenMenu = false
                        }
                    val permissionLauncherFiles = rememberLauncherForActivityResult(
                        ActivityResultContracts.RequestPermission()
                    ) {
                        if (it) {
                            launcherFiles.launch(mimeType)
                        } else {
                            Toast.makeText(context, "Permission Denied", Toast.LENGTH_SHORT)
                                .show()
                        }
                    }
                    val launcherCamera =
                        rememberLauncherForActivityResult(ActivityResultContracts.TakePicture()) {
                            if (it) {
                                onAttachment(listOf(tempUri))
                            }
                            isOpenMenu = false
                        }
                    val permissionLauncherCamera = rememberLauncherForActivityResult(
                        ActivityResultContracts.RequestPermission()
                    ) {
                        if (it) {
                            val file = context.createFile(".jpeg")
                            tempUri = FileProvider.getUriForFile(
                                context,
                                BuildConfig.APPLICATION_ID + ".provider", file
                            )
                            launcherCamera.launch(tempUri)
                        } else {
                            Toast.makeText(context, "Permission Denied", Toast.LENGTH_SHORT)
                                .show()
                        }
                    }
                    Column {
                        AttachmentButton(
                            color = MaterialTheme.colorScheme.primary,
                            onClick = {
                                permissionLauncherFiles.launch(Manifest.permission.READ_EXTERNAL_STORAGE)
                            },
                            text = {
                                Text(text = "File", style = MaterialTheme.typography.bodySmall)
                            }) {
                            Icon(
                                imageVector = Icons.Default.AttachFile,
                                contentDescription = "",
                                tint = Color.White
                            )
                        }
                        Spacer(modifier = Modifier.size(32.dp))
                        AttachmentButton(color = Color.Orange, onClick = {
                            mimeType = arrayOf(
                                "audio/*"
                            )
                            permissionLauncherFiles.launch(Manifest.permission.READ_EXTERNAL_STORAGE)
                        }, text = {
                            Text(text = "Audio", style = MaterialTheme.typography.bodySmall)
                        }) {
                            Icon(
                                imageVector = Icons.Default.Headset,
                                contentDescription = "",
                                tint = Color.White
                            )
                        }
                    }
                    Spacer(modifier = Modifier.size(16.dp))
                    Column {
                        AttachmentButton(color = Color.Red, onClick = {
                            permissionLauncherCamera.launch(Manifest.permission.CAMERA)
                        }, text = {
                            Text(text = "Camera", style = MaterialTheme.typography.bodySmall)
                        }) {
                            Icon(
                                imageVector = Icons.Default.Camera,
                                contentDescription = "",
                                tint = Color.White
                            )
                        }
                        Spacer(modifier = Modifier.size(32.dp))
                        AttachmentButton(color = Color.DarkLimeGreen, onClick = {}, text = {
                            Text(text = "Location", style = MaterialTheme.typography.bodySmall)
                        }) {
                            Icon(
                                imageVector = Icons.Default.LocationOn,
                                contentDescription = "",
                                tint = Color.White
                            )
                        }
                    }
                    Spacer(modifier = Modifier.size(16.dp))
                    Column {
                        AttachmentButton(color = Color.Purple, onClick = {
                            mimeType = arrayOf(
                                "image/*",
                                "video/*"
                            )
                            permissionLauncherFiles.launch(Manifest.permission.READ_EXTERNAL_STORAGE)
                        }, text = {
                            Text(text = "Gallery", style = MaterialTheme.typography.bodySmall)
                        }) {
                            Icon(
                                imageVector = Icons.Default.Image,
                                contentDescription = "",
                                tint = Color.White
                            )
                        }
                        Spacer(modifier = Modifier.size(32.dp))
                        AttachmentButton(color = Color.BlueSky, onClick = {}, text = {
                            Text(text = "Contact", style = MaterialTheme.typography.bodySmall)
                        }) {
                            Icon(
                                imageVector = Icons.Default.Person,
                                contentDescription = "",
                                tint = Color.White
                            )
                        }
                    }
                }
            }
        }
    }
}

@Composable
fun AttachmentButton(
    color: Color = MaterialTheme.colorScheme.primary,
    onClick: () -> Unit,
    text: @Composable () -> Unit,
    content: @Composable () -> Unit
) {
    Column(horizontalAlignment = Alignment.CenterHorizontally) {
        Box(
            modifier = Modifier
                .then(Modifier.size(72.dp))
                .graphicsLayer {
                    shape = CircleShape
                    clip = true
                }
                .clickable(onClick = onClick)
                .padding(0.dp)
                .background(color),
            contentAlignment = Alignment.Center
        ) {
            content()
        }
        Spacer(modifier = Modifier.size(6.dp))
        text()
    }
}

fun Context.getAttachmentItem(uri: Uri): AttachmentItem? {
    val item = contentResolver.query(uri, null, null, null, null)
        ?.use { cursor ->
            val nameIndex =
                cursor.getColumnIndex(OpenableColumns.DISPLAY_NAME)
            val sizeIndex = cursor.getColumnIndex(OpenableColumns.SIZE)
            cursor.moveToFirst()
            AttachmentItem(
                cursor.getString(nameIndex),
                cursor.getLong(sizeIndex),
                getMimeType(uri),
                uri
            )
        }
    return item
}

object UriSerializable : KSerializer<Uri> {
    override val descriptor: SerialDescriptor
        get() = PrimitiveSerialDescriptor("Uri", PrimitiveKind.STRING)

    override fun deserialize(decoder: Decoder): Uri {
        return decoder.decodeString().toUri()
    }

    override fun serialize(encoder: Encoder, value: Uri) {
        encoder.encodeString(value.toString())
    }

}

@Serializable
@Parcelize
data class AttachmentItem(
    val name: String,
    val size: Long,
    val mimeType: String,
    @Serializable(with = UriSerializable::class)
    val uri: Uri
) : Parcelable

@Serializable
@Parcelize
data class AttachmentItemList(
    val list: List<AttachmentItem?>
) : Parcelable

val AttachmentItemListType = object : NavType<AttachmentItemList>(isNullableAllowed = false) {
    override fun put(bundle: Bundle, key: String, value: AttachmentItemList) {
        bundle.putParcelable(key, value)
    }

    override fun get(bundle: Bundle, key: String): AttachmentItemList? {
        return bundle.getParcelable<AttachmentItemList>(key)
    }

    override fun parseValue(value: String): AttachmentItemList {
        return Json.decodeFromString<AttachmentItemList>(value)
    }
}

@Composable
fun AttachmentCaption(
    navController: NavHostController,
    pin: String,
    attachments: AttachmentItemList
) {
    var textInput by rememberSaveable(stateSaver = TextFieldValue.Saver) {
        mutableStateOf(TextFieldValue("", TextRange(0, 7)))
    }
    val messageModel: MessageViewModel = hiltViewModel()
    val context = LocalContext.current
    Column(modifier = Modifier.fillMaxSize()) {
        attachments.list[0]?.let {
            if (it.mimeType.startsWith("image")) {
                AsyncImage(
                    model = ImageRequest.Builder(LocalContext.current)
                        .data(it.uri)
                        .addHeader("Cookie", "PHPSESSID=123;MOBILE=123")
                        .crossfade(true)
                        .build(),
                    placeholder = painterResource(R.drawable.ic_placeholder),
                    contentDescription = "",
                    contentScale = ContentScale.Fit,
                    modifier = Modifier
                        .weight(1f)
                )
            }
        }
        TextField(
            modifier = Modifier
                .fillMaxWidth()
                .graphicsLayer {
                    shape = CircleShape
                    clip = true
                },
            value = textInput,
            onValueChange = { textInput = it },
            label = null,
            placeholder = {
                Text(text = "Add a caption...", color = MaterialTheme.colorScheme.onSurface)
            },
            trailingIcon = {
                Row {
                    IconButton(onClick = {
                        val me = context.getSharedPreferences().getString("pin", null)
                        me?.let {
                            attachments.list[0]?.let { item ->
                                messageModel.send(
                                    context,
                                    Message(
                                        message_id = System.nanoTime().toString(),
                                        f_pin = it,
                                        l_pin = pin,
                                        message_scope_id = "3", // 3: chat, 15: sms, 16: email
                                        server_date = System.currentTimeMillis(),
                                        status = "1",
                                        message_text = textInput.text,
                                        opposite_pin = pin,
                                        f_display_name = "",
                                        message_large_text = "",
                                        message_text_plain = "",
                                        uri = item.uri
                                    )
                                )
                            }
                        }
                        textInput = TextFieldValue("")
                        navController.popBackStack()
                    }) {
                        Icon(
                            imageVector = Icons.AutoMirrored.Filled.Send,
                            contentDescription = "",
                            tint = MaterialTheme.colorScheme.primary
                        )
                    }
                }
            },
            colors = TextFieldDefaults.colors(
                focusedContainerColor = MaterialTheme.colorScheme.surface,
                unfocusedContainerColor = MaterialTheme.colorScheme.surface,
                disabledContainerColor = MaterialTheme.colorScheme.surface,
                focusedIndicatorColor = Color.Transparent,
                unfocusedIndicatorColor = Color.Transparent,
                disabledIndicatorColor = Color.Transparent,
                errorIndicatorColor = Color.Transparent,
            ),
            keyboardOptions = KeyboardOptions(KeyboardCapitalization.Sentences),
            maxLines = 3
        )
    }
}