package top.yeij.cyrene.ui.screens.chat

import android.net.Uri
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.animation.AnimatedVisibility
import androidx.compose.animation.fadeIn
import androidx.compose.animation.slideInVertically
import androidx.compose.animation.core.tween
import androidx.compose.foundation.background
import androidx.compose.foundation.border
import androidx.compose.foundation.clickable
import androidx.compose.foundation.gestures.detectDragGesturesAfterLongPress
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.Spacer
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.fillMaxWidth
import androidx.compose.foundation.layout.height
import androidx.compose.foundation.layout.imePadding
import androidx.compose.foundation.layout.navigationBarsPadding
import androidx.compose.foundation.layout.offset
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.statusBarsPadding
import androidx.compose.foundation.layout.width
import androidx.compose.foundation.lazy.LazyColumn
import androidx.compose.foundation.lazy.LazyRow
import androidx.compose.foundation.lazy.itemsIndexed
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.text.KeyboardActions
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.AddPhotoAlternate
import androidx.compose.material.icons.filled.Close
import androidx.compose.material.icons.filled.KeyboardVoice
import androidx.compose.material.icons.filled.Lock
import androidx.compose.material.icons.filled.Mic
import androidx.compose.material.icons.filled.Refresh
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.Icon
import androidx.compose.material3.IconButton
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Text
import androidx.compose.runtime.Composable
import androidx.compose.runtime.LaunchedEffect
import androidx.compose.runtime.collectAsState
import androidx.compose.runtime.derivedStateOf
import androidx.compose.runtime.getValue
import androidx.compose.runtime.mutableStateOf
import androidx.compose.runtime.remember
import androidx.compose.runtime.setValue
import androidx.compose.runtime.snapshotFlow
import androidx.compose.ui.Alignment
import androidx.compose.ui.Modifier
import androidx.compose.ui.draw.clip
import androidx.compose.ui.input.pointer.pointerInput
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.layout.onGloballyPositioned
import androidx.compose.ui.layout.positionInRoot
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.text.input.ImeAction
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.IntOffset
import androidx.compose.ui.unit.dp
import coil.compose.AsyncImage
import coil.request.ImageRequest
import kotlinx.coroutines.delay
import org.koin.androidx.compose.koinViewModel
import org.koin.compose.koinInject
import top.yeij.cyrene.domain.model.Message
import top.yeij.cyrene.ui.components.ChatBubble
import top.yeij.cyrene.ui.components.CyreneStatus
import top.yeij.cyrene.ui.components.StatusIndicator
import top.yeij.cyrene.ui.components.TypingIndicator
import top.yeij.cyrene.util.RecordState
import top.yeij.cyrene.util.RuntimeLog
import top.yeij.cyrene.viewmodel.ChatViewModel
import top.yeij.cyrene.viewmodel.SettingsViewModel
import kotlin.math.min


@Composable
private fun AnimatedChatBubble(
    message: Message,
    animIndex: Int,
) {
    var visible by remember { mutableStateOf(false) }
    LaunchedEffect(Unit) {
        delay(min(animIndex, 10) * 60L)
        visible = true
    }
    AnimatedVisibility(
        visible = visible,
        enter = fadeIn(animationSpec = tween(300)) +
            slideInVertically(
                animationSpec = tween(300),
                initialOffsetY = { it / 4 },
            ),
    ) {
        ChatBubble(
            content = message.content,
            role = message.role,
            msgType = message.msgType,
            timestamp = message.timestamp,
            imageDataUris = message.imageDataUris,
        )
    }
}

@Composable
fun ChatScreen(
    viewModel: ChatViewModel = koinViewModel(),
    settingsViewModel: SettingsViewModel = koinInject(),
) {
    // Track composition to diagnose navigation-related issues
    LaunchedEffect(Unit) {
        RuntimeLog.general("chat", "ChatScreen composed, ChatViewModel instance resolved")
    }
    val messages by viewModel.currentMessages.collectAsState()
    val inputText by viewModel.inputText.collectAsState()
    val isStreaming by viewModel.isStreaming.collectAsState()
    val isConnected by viewModel.isConnected.collectAsState()
    val isRefreshing by viewModel.isRefreshing.collectAsState()
    val recordState by viewModel.voiceRecordState.collectAsState()
    val recordDurationMs by viewModel.voiceRecordDurationMs.collectAsState()
    val animIndex by viewModel.messageAnimIndex.collectAsState()
    val typingIndicatorStyle by settingsViewModel.typingIndicatorStyle.collectAsState()
    val enterToSend by settingsViewModel.enterToSend.collectAsState()

    // reverseLayout: index 0 = newest (visual bottom), index N-1 = oldest (visual top)
    val listState = rememberLazyListState()

    // Track whether user is near the latest messages (visual bottom = index 0)
    val isNearBottom by remember {
        derivedStateOf {
            val info = listState.layoutInfo
            if (info.totalItemsCount == 0) return@derivedStateOf true
            (info.visibleItemsInfo.firstOrNull()?.index ?: 0) <= 2
        }
    }

    // Gesture tracking state
    var isDragging by remember { mutableStateOf(false) }
    var dragOffsetX by remember { mutableStateOf(0f) }
    var dragOffsetY by remember { mutableStateOf(0f) }
    var recordButtonY by remember { mutableStateOf(0f) }

    val recordSec = recordDurationMs / 1000f
    val isRecording = recordState == RecordState.RECORDING
    val isLocked = recordState == RecordState.LOCKED
    val inCancelZone = isDragging && dragOffsetY < -120f
    val inLockZone = isDragging && dragOffsetX > 60f

    // Image picker
    val selectedImages by viewModel.selectedImageUris.collectAsState()
    val imagePickerLauncher = rememberLauncherForActivityResult(
        contract = ActivityResultContracts.GetMultipleContents()
    ) { uris: List<Uri> ->
        if (uris.isNotEmpty()) {
            viewModel.addImages(uris)
        }
    }
    val context = LocalContext.current

    // Stay at bottom for new messages unless user scrolled up
    LaunchedEffect(Unit) {
        snapshotFlow { messages.size to isNearBottom }
            .collect { (_, nearBottom) ->
                if (nearBottom && listState.firstVisibleItemIndex != 0) {
                    listState.animateScrollToItem(0)
                }
            }
    }

    // Animated "昔涟正在输入..." dots
    val typingDots = remember { mutableStateOf("") }
    LaunchedEffect(isStreaming) {
        if (isStreaming) {
            val dots = arrayOf("", ".", "..", "...")
            var i = 0
            while (true) {
                typingDots.value = dots[i % 4]
                i++
                delay(400)
            }
        } else {
            typingDots.value = ""
        }
    }

    val status = when {
        isStreaming -> CyreneStatus.THINKING
        isConnected -> CyreneStatus.ONLINE
        else -> CyreneStatus.OFFLINE
    }

    // Single column layout: everything flows together and IME shrinks the whole view
    Column(
        modifier = Modifier
            .fillMaxSize()
            .statusBarsPadding()
            .imePadding(),
    ) {
        // Top status bar with refresh button
        Row(
            modifier = Modifier
                .fillMaxWidth()
                .padding(horizontal = 16.dp, vertical = 8.dp),
            verticalAlignment = Alignment.CenterVertically,
        ) {
            StatusIndicator(status = status)
            Spacer(modifier = Modifier.weight(1f))
            IconButton(
                onClick = { viewModel.refreshMessages() },
                enabled = !isRefreshing,
            ) {
                if (isRefreshing) {
                    CircularProgressIndicator(
                        modifier = Modifier.size(20.dp),
                        strokeWidth = 2.dp,
                    )
                } else {
                    Icon(
                        Icons.Filled.Refresh,
                        contentDescription = "刷新",
                        tint = MaterialTheme.colorScheme.onSurfaceVariant,
                    )
                }
            }
        }

        // Selected images preview
        if (selectedImages.isNotEmpty()) {
            LazyRow(
                modifier = Modifier
                    .fillMaxWidth()
                    .padding(horizontal = 12.dp, vertical = 4.dp),
                horizontalArrangement = Arrangement.spacedBy(8.dp),
            ) {
                itemsIndexed(selectedImages, key = { i, _ -> i }) { index, uri ->
                    Box(
                        modifier = Modifier
                            .size(72.dp)
                            .clip(RoundedCornerShape(8.dp))
                            .border(1.dp, MaterialTheme.colorScheme.outlineVariant, RoundedCornerShape(8.dp)),
                    ) {
                        AsyncImage(
                            model = ImageRequest.Builder(context)
                                .data(uri)
                                .crossfade(true)
                                .build(),
                            contentDescription = "已选图片",
                            modifier = Modifier.fillMaxSize(),
                            contentScale = ContentScale.Crop,
                        )
                        IconButton(
                            onClick = { viewModel.removeImage(index) },
                            modifier = Modifier
                                .align(Alignment.TopEnd)
                                .size(20.dp)
                                .padding(0.dp),
                        ) {
                            Icon(
                                Icons.Default.Close,
                                contentDescription = "移除",
                                tint = MaterialTheme.colorScheme.onErrorContainer,
                                modifier = Modifier
                                    .size(14.dp)
                                    .background(
                                        MaterialTheme.colorScheme.errorContainer.copy(alpha = 0.8f),
                                        CircleShape,
                                    ),
                            )
                        }
                    }
                }
            }
        }

        // Messages area (fills remaining space, shrinks with IME)
        Box(modifier = Modifier.weight(1f)) {
            if (messages.isEmpty() && !isStreaming) {
                Box(
                    modifier = Modifier.fillMaxSize(),
                    contentAlignment = Alignment.Center,
                ) {
                    Text(
                        text = "开始和昔涟对话吧",
                        style = MaterialTheme.typography.bodyLarge,
                        color = MaterialTheme.colorScheme.onSurfaceVariant,
                    )
                }
            } else {
                LazyColumn(
                    modifier = Modifier.fillMaxSize(),
                    state = listState,
                    reverseLayout = true,
                ) {
                    if (isStreaming && typingIndicatorStyle != "text") {
                        item(key = "typing_indicator") {
                            TypingIndicator()
                        }
                    }
                    itemsIndexed(messages, key = { _, msg -> msg.id }) { index, message ->
                        AnimatedChatBubble(
                            message = message,
                            animIndex = index.coerceAtMost(20),
                        )
                    }
                }
            }
        }

        // Input area at bottom, in flow (not overlaid)
        Column(
            modifier = Modifier
                .fillMaxWidth()
                .background(MaterialTheme.colorScheme.surface)
                .navigationBarsPadding(),
        ) {
            // "昔涟正在输入..." indicator (text mode only)
            if (isStreaming && typingIndicatorStyle == "text") {
                Text(
                    text = "昔涟正在输入${typingDots.value}",
                    style = MaterialTheme.typography.labelSmall,
                    color = MaterialTheme.colorScheme.primary,
                    modifier = Modifier
                        .fillMaxWidth()
                        .padding(horizontal = 16.dp, vertical = 2.dp),
                    textAlign = TextAlign.Start,
                )
            }

            Row(
                modifier = Modifier
                    .fillMaxWidth()
                    .padding(horizontal = 12.dp, vertical = 8.dp),
                verticalAlignment = Alignment.CenterVertically,
            ) {
                if (isRecording && isDragging) {
                    Box(
                        modifier = Modifier
                            .weight(1f)
                            .clip(RoundedCornerShape(12.dp))
                            .background(
                                if (inCancelZone) MaterialTheme.colorScheme.errorContainer
                                else MaterialTheme.colorScheme.surfaceVariant
                            )
                            .padding(horizontal = 16.dp, vertical = 14.dp),
                        contentAlignment = Alignment.Center,
                    ) {
                        Text(
                            text = when {
                                inCancelZone -> "松手取消"
                                inLockZone -> "松手录音"
                                else -> "%.1f\" 上滑取消 右滑松手".format(recordSec)
                            },
                            style = MaterialTheme.typography.bodyMedium,
                            color = if (inCancelZone) MaterialTheme.colorScheme.error
                                    else MaterialTheme.colorScheme.onSurfaceVariant,
                        )
                    }
                    Box(
                        modifier = Modifier
                            .padding(start = 8.dp)
                            .size(48.dp)
                            .clip(CircleShape)
                            .background(MaterialTheme.colorScheme.primary)
                            .offset { IntOffset(dragOffsetX.toInt(), dragOffsetY.toInt()) },
                        contentAlignment = Alignment.Center,
                    ) {
                        Icon(
                            Icons.Filled.Mic,
                            contentDescription = "录音中",
                            tint = MaterialTheme.colorScheme.onPrimary,
                        )
                    }
                } else if (isLocked) {
                    Box(
                        modifier = Modifier
                            .weight(1f)
                            .clip(RoundedCornerShape(12.dp))
                            .background(MaterialTheme.colorScheme.primaryContainer)
                            .padding(horizontal = 16.dp, vertical = 14.dp),
                        contentAlignment = Alignment.Center,
                    ) {
                        Row(verticalAlignment = Alignment.CenterVertically) {
                            Icon(
                                Icons.Filled.Lock,
                                contentDescription = null,
                                modifier = Modifier.size(16.dp),
                                tint = MaterialTheme.colorScheme.onPrimaryContainer,
                            )
                            Spacer(modifier = Modifier.width(8.dp))
                            Text(
                                text = "%.1f\" 松手录音中 — 点击结束".format(recordSec),
                                style = MaterialTheme.typography.bodyMedium,
                                color = MaterialTheme.colorScheme.onPrimaryContainer,
                            )
                        }
                    }
                    IconButton(onClick = { viewModel.finishRecord() }) {
                        Icon(
                            Icons.AutoMirrored.Filled.Send,
                            contentDescription = "发送",
                            tint = MaterialTheme.colorScheme.primary,
                        )
                    }
                } else {
                    IconButton(
                        onClick = { imagePickerLauncher.launch("image/*") },
                    ) {
                        Icon(
                            Icons.Default.AddPhotoAlternate,
                            contentDescription = "添加图片",
                            tint = MaterialTheme.colorScheme.onSurfaceVariant,
                        )
                    }
                    OutlinedTextField(
                        value = inputText,
                        onValueChange = { viewModel.onInputChanged(it) },
                        placeholder = { Text("输入消息...") },
                        modifier = Modifier.weight(1f),
                        maxLines = 4,
                        shape = MaterialTheme.shapes.medium,
                        keyboardOptions = if (enterToSend) {
                            KeyboardOptions(imeAction = ImeAction.Done)
                        } else {
                            KeyboardOptions.Default
                        },
                        keyboardActions = if (enterToSend) {
                            KeyboardActions(
                                onDone = { if (inputText.isNotBlank()) viewModel.sendMessage() },
                            )
                        } else {
                            KeyboardActions.Default
                        },
                    )
                    Box(
                        modifier = Modifier
                            .padding(start = 4.dp)
                            .size(48.dp)
                            .onGloballyPositioned { recordButtonY = it.positionInRoot().y }
                            .pointerInput(Unit) {
                                detectDragGesturesAfterLongPress(
                                    onDragStart = { offset ->
                                        isDragging = true
                                        dragOffsetX = 0f
                                        dragOffsetY = 0f
                                        viewModel.startRecord()
                                    },
                                    onDrag = { change, dragAmount ->
                                        change.consume()
                                        dragOffsetX += dragAmount.x
                                        dragOffsetY += dragAmount.y
                                    },
                                    onDragEnd = {
                                        isDragging = false
                                        when {
                                            dragOffsetY < -120f -> viewModel.cancelRecord()
                                            dragOffsetX > 60f -> viewModel.lockRecord()
                                            else -> viewModel.finishRecord()
                                        }
                                        dragOffsetX = 0f
                                        dragOffsetY = 0f
                                    },
                                    onDragCancel = {
                                        isDragging = false
                                        viewModel.cancelRecord()
                                        dragOffsetX = 0f
                                        dragOffsetY = 0f
                                    },
                                )
                            },
                        contentAlignment = Alignment.Center,
                    ) {
                        Icon(
                            Icons.Filled.KeyboardVoice,
                            contentDescription = "按住录音",
                            tint = MaterialTheme.colorScheme.onSurfaceVariant,
                        )
                    }
                    if (inputText.isNotBlank()) {
                        IconButton(
                            onClick = { viewModel.sendMessage() },
                            enabled = !isStreaming,
                        ) {
                            if (isStreaming) {
                                CircularProgressIndicator(
                                    modifier = Modifier.size(24.dp),
                                    strokeWidth = 2.dp,
                                )
                            } else {
                                Icon(
                                    Icons.AutoMirrored.Filled.Send,
                                    contentDescription = "发送",
                                    tint = MaterialTheme.colorScheme.onSurfaceVariant,
                                )
                            }
                        }
                    }
                }
            }
        }
    }
}
