package com.jidan.jiaoyi.ui

import android.app.Activity
import android.content.ActivityNotFoundException
import android.content.Intent
import android.net.Uri
import android.speech.RecognizerIntent
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.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.PaddingValues
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.heightIn
import androidx.compose.foundation.layout.imePadding
import androidx.compose.foundation.layout.navigationBarsPadding
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.items
import androidx.compose.foundation.lazy.rememberLazyListState
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.material3.Button
import androidx.compose.material3.ButtonDefaults
import androidx.compose.material3.CircularProgressIndicator
import androidx.compose.material3.HorizontalDivider
import androidx.compose.material3.MaterialTheme
import androidx.compose.material3.OutlinedTextField
import androidx.compose.material3.Scaffold
import androidx.compose.material3.Surface
import androidx.compose.material3.Text
import androidx.compose.material3.TextButton
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.graphics.Color
import androidx.compose.ui.platform.LocalClipboardManager
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.text.AnnotatedString
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.text.style.TextAlign
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import com.jidan.jiaoyi.data.AiClient
import com.jidan.jiaoyi.data.AiConversationStore
import com.jidan.jiaoyi.data.AiMessage
import com.jidan.jiaoyi.data.AppUpdateInfo
import com.jidan.jiaoyi.BuildConfig
import kotlinx.coroutines.Job
import kotlinx.coroutines.launch
import java.util.Locale
import java.util.UUID

private val BrandRed = Color(0xFFE3262E)
private val DeepRed = Color(0xFFB71921)
private val SoftRed = Color(0xFFFFE8EA)
private val AppBackground = Color(0xFFF6F6F6)
private val Ink = Color(0xFF202020)
private val Muted = Color(0xFF777777)
private val Line = Color(0xFFE7E7E7)

private val starterQuestions = listOf(
    "胶州二中坐哪路？",
    "胶州今天天气怎么样？",
    "丝路千古情好玩吗？",
    "去三里河怎么走？",
)

@Composable
fun JiaoyiAiTheme(content: @Composable () -> Unit) {
    MaterialTheme(
        colorScheme = androidx.compose.material3.lightColorScheme(
            primary = BrandRed,
            onPrimary = Color.White,
            primaryContainer = SoftRed,
            onPrimaryContainer = DeepRed,
            background = AppBackground,
            onBackground = Ink,
            surface = Color.White,
            onSurface = Ink,
            outline = Line,
        ),
        content = content,
    )
}

@Composable
fun JiaoyiAiApp(conversationStore: AiConversationStore) {
    val aiClient = remember { AiClient() }
    val scope = rememberCoroutineScope()
    val listState = rememberLazyListState()
    val context = LocalContext.current
    val clipboard = LocalClipboardManager.current
    var messages by remember { mutableStateOf(conversationStore.loadMessages()) }
    var sessionId by remember { mutableStateOf(conversationStore.newSessionId()) }
    var draft by remember { mutableStateOf(conversationStore.loadDraft()) }
    var thinking by remember { mutableStateOf(false) }
    var notice by remember { mutableStateOf<String?>(null) }
    var suggestions by remember { mutableStateOf(starterQuestions) }
    var localBrainAvailable by remember { mutableStateOf<Boolean?>(null) }
    var requestJob by remember { mutableStateOf<Job?>(null) }
    var contributionContext by remember { mutableStateOf<List<AiMessage>>(emptyList()) }
    var availableUpdate by remember { mutableStateOf<AppUpdateInfo?>(null) }
    val contributing = contributionContext.isNotEmpty()

    fun replaceMessages(next: List<AiMessage>) {
        messages = next.takeLast(200)
        conversationStore.saveMessages(messages)
    }

    fun startContribution(target: AiMessage) {
        if (thinking) return
        val targetIndex = messages.indexOfFirst { it.id == target.id }
        if (targetIndex < 0) return
        val question = messages
            .take(targetIndex)
            .lastOrNull { it.role == "user" }
        contributionContext = listOfNotNull(question, target)
        draft = ""
        notice = null
    }

    fun submitQuestion(value: String) {
        val question = value.trim().take(160)
        if (question.isBlank() || thinking || contributing) return
        val userMessage = AiMessage(
            id = UUID.randomUUID().toString(),
            role = "user",
            text = question,
            createdAt = System.currentTimeMillis(),
        )
        replaceMessages(messages + userMessage)
        draft = ""
        notice = null
        thinking = true
        requestJob = scope.launch {
            runCatching { aiClient.ask(question, sessionId) }
                .onSuccess { reply ->
                    replaceMessages(
                        messages + AiMessage(
                            id = UUID.randomUUID().toString(),
                            role = "assistant",
                            text = reply.answer,
                            createdAt = System.currentTimeMillis(),
                            source = reply.source,
                        ),
                    )
                    if (reply.suggestions.isNotEmpty()) suggestions = reply.suggestions
                    localBrainAvailable = reply.localBrainAvailable
                }
                .onFailure { error ->
                    if (error is kotlinx.coroutines.CancellationException) {
                        notice = "已停止，问题还在输入框里"
                    } else {
                        notice = error.message ?: "暂时没接上，问题已保留，可直接重试。"
                    }
                    draft = question
                }
            thinking = false
            requestJob = null
        }
    }

    fun submitContribution(value: String) {
        val contribution = value.trim().take(500)
        val submittedContext = contributionContext
        if (contribution.isBlank() || thinking || submittedContext.isEmpty()) return
        val currentMessages = messages
        val userMessage = AiMessage(
            id = UUID.randomUUID().toString(),
            role = "user",
            text = contribution,
            createdAt = System.currentTimeMillis(),
        )
        draft = ""
        notice = null
        thinking = true
        requestJob = scope.launch {
            runCatching {
                aiClient.contribute(
                    message = contribution,
                    sessionId = sessionId,
                    context = submittedContext,
                )
            }.onSuccess { reply ->
                val immediate = reply.autoApplied || reply.status == "learned"
                val acknowledgement = if (
                    immediate &&
                    !Regex("即时|立即|马上生效").containsMatchIn(reply.answer)
                ) {
                    "${reply.answer}\n\n已加入胶易共创，马上生效。"
                } else {
                    reply.answer
                }
                replaceMessages(
                    currentMessages + userMessage + AiMessage(
                        id = UUID.randomUUID().toString(),
                        role = "assistant",
                        text = acknowledgement,
                        createdAt = System.currentTimeMillis(),
                        source = "胶易开放共创库",
                    ),
                )
                contributionContext = emptyList()
                notice = if (immediate) "共创补充已即时生效" else "共创补充已提交"
            }.onFailure { error ->
                if (
                    error is kotlinx.coroutines.CancellationException &&
                    contributionContext.isNotEmpty()
                ) {
                    notice = "已停止，共创内容还在输入框里"
                } else if (error !is kotlinx.coroutines.CancellationException) {
                    notice = error.message ?: "这次没记下来，稍后再试。"
                }
                if (contributionContext.isNotEmpty()) draft = contribution
            }
            thinking = false
            requestJob = null
        }
    }

    val speechLauncher = rememberLauncherForActivityResult(
        ActivityResultContracts.StartActivityForResult(),
    ) { result ->
        if (result.resultCode == Activity.RESULT_OK) {
            val text = result.data
                ?.getStringArrayListExtra(RecognizerIntent.EXTRA_RESULTS)
                ?.firstOrNull()
                .orEmpty()
            if (text.isNotBlank()) {
                draft = listOf(draft.trim(), text.trim())
                    .filter(String::isNotBlank)
                    .joinToString(" ")
                    .take(if (contributing) 500 else 160)
            }
        }
    }

    fun startSpeechInput() {
        val intent = Intent(RecognizerIntent.ACTION_RECOGNIZE_SPEECH).apply {
            putExtra(RecognizerIntent.EXTRA_LANGUAGE_MODEL, RecognizerIntent.LANGUAGE_MODEL_FREE_FORM)
            putExtra(RecognizerIntent.EXTRA_LANGUAGE, Locale.SIMPLIFIED_CHINESE.toLanguageTag())
            putExtra(RecognizerIntent.EXTRA_PROMPT, "说完后确认发送")
        }
        try {
            speechLauncher.launch(intent)
        } catch (_: ActivityNotFoundException) {
            notice = "这台手机没有可用的语音输入服务。"
        }
    }

    fun shareConversation() {
        if (messages.isEmpty()) {
            notice = "当前还没有可分享的对话。"
            return
        }
        val transcript = buildString {
            appendLine("胶易 AI 对话")
            appendLine()
            messages.forEach { message ->
                appendLine(if (message.role == "user") "我：" else "胶易 AI：")
                appendLine(message.text)
                message.source?.takeIf(String::isNotBlank)?.let {
                    appendLine("来源：$it")
                }
                appendLine()
            }
        }
        runCatching {
            context.startActivity(
                Intent.createChooser(
                    Intent(Intent.ACTION_SEND).apply {
                        type = "text/plain"
                        putExtra(Intent.EXTRA_TEXT, transcript)
                    },
                    "分享胶易对话",
                ),
            )
        }.onFailure {
            notice = "这台手机暂时没有可用的分享应用。"
        }
    }

    LaunchedEffect(draft) {
        conversationStore.saveDraft(draft)
    }

    LaunchedEffect(Unit) {
        availableUpdate = runCatching {
            aiClient.checkForUpdate(BuildConfig.VERSION_CODE)
        }.getOrNull()
    }

    LaunchedEffect(messages.size, thinking) {
        if (messages.isNotEmpty()) listState.animateScrollToItem(messages.lastIndex)
    }

    Scaffold(
        containerColor = AppBackground,
        topBar = {
            JiaoyiTopBar(
                localBrainAvailable = localBrainAvailable,
                update = availableUpdate,
                shareEnabled = messages.isNotEmpty(),
                onShare = ::shareConversation,
                onOpenUpdate = { update ->
                    runCatching {
                        context.startActivity(
                            Intent(Intent.ACTION_VIEW, Uri.parse(update.pageUrl)),
                        )
                    }.onFailure {
                        notice = "请打开 www.jiaoyi123.cn/xiazai/ 更新。"
                    }
                },
                onNewChat = {
                    requestJob?.cancel()
                    requestJob = null
                    thinking = false
                    sessionId = conversationStore.newSessionId()
                    suggestions = starterQuestions
                    contributionContext = emptyList()
                    draft = ""
                    notice = if (messages.isEmpty()) {
                        "已开始新对话"
                    } else {
                        "已开始新对话，旧记录仍保留在上方"
                    }
                },
            )
        },
        bottomBar = {
            Composer(
                value = draft,
                thinking = thinking,
                contributing = contributing,
                notice = notice,
                onValueChange = { draft = it.take(if (contributing) 500 else 160) },
                onVoice = ::startSpeechInput,
                onSend = {
                    if (contributing) submitContribution(draft) else submitQuestion(draft)
                },
                onStop = { requestJob?.cancel() },
                onCancelContribution = {
                    requestJob?.cancel()
                    requestJob = null
                    thinking = false
                    contributionContext = emptyList()
                    draft = ""
                    notice = "已取消共创补充"
                },
            )
        },
    ) { innerPadding ->
        if (messages.isEmpty()) {
            Welcome(
                modifier = Modifier.padding(innerPadding),
                suggestions = suggestions,
                onQuestion = ::submitQuestion,
            )
        } else {
            LazyColumn(
                state = listState,
                modifier = Modifier
                    .fillMaxSize()
                    .padding(innerPadding),
                contentPadding = PaddingValues(horizontal = 14.dp, vertical = 18.dp),
                verticalArrangement = Arrangement.spacedBy(12.dp),
            ) {
                items(messages, key = AiMessage::id) { message ->
                    MessageBubble(
                        message = message,
                        contributionEnabled = !thinking,
                        onCopy = {
                            clipboard.setText(AnnotatedString(message.text))
                            notice = "已复制"
                        },
                        onContribute = { startContribution(message) },
                    )
                }
                if (thinking) {
                    item {
                        Row(
                            modifier = Modifier.fillMaxWidth(),
                            horizontalArrangement = Arrangement.Start,
                        ) {
                            Surface(
                                shape = RoundedCornerShape(16.dp),
                                color = Color.White,
                            ) {
                                Row(
                                    modifier = Modifier.padding(horizontal = 16.dp, vertical = 12.dp),
                                    verticalAlignment = Alignment.CenterVertically,
                                ) {
                                    CircularProgressIndicator(
                                        modifier = Modifier.size(18.dp),
                                        strokeWidth = 2.dp,
                                        color = BrandRed,
                                    )
                                    Spacer(Modifier.width(10.dp))
                                    Text(
                                        if (contributing) "正在加入开放共创…" else "理解问题，整理答案…",
                                        color = Muted,
                                        fontSize = 14.sp,
                                    )
                                }
                            }
                        }
                    }
                }
                if (!thinking && suggestions.isNotEmpty()) {
                    item {
                        Column(verticalArrangement = Arrangement.spacedBy(7.dp)) {
                            suggestions.take(4).forEach { suggestion ->
                                Text(
                                    text = suggestion,
                                    modifier = Modifier
                                        .clip(RoundedCornerShape(18.dp))
                                        .background(Color.White)
                                        .clickable { submitQuestion(suggestion) }
                                        .padding(horizontal = 13.dp, vertical = 8.dp),
                                    color = DeepRed,
                                    fontSize = 13.sp,
                                )
                            }
                        }
                    }
                }
            }
        }
    }
}

@Composable
private fun JiaoyiTopBar(
    localBrainAvailable: Boolean?,
    update: AppUpdateInfo?,
    shareEnabled: Boolean,
    onShare: () -> Unit,
    onOpenUpdate: (AppUpdateInfo) -> Unit,
    onNewChat: () -> Unit,
) {
    Column(
        modifier = Modifier
            .fillMaxWidth()
            .background(Color.White)
            .statusBarsPadding(),
    ) {
        Row(
            modifier = Modifier
                .fillMaxWidth()
                .height(60.dp)
                .padding(horizontal = 14.dp),
            verticalAlignment = Alignment.CenterVertically,
        ) {
            Box(
                modifier = Modifier
                    .size(38.dp)
                    .clip(RoundedCornerShape(11.dp))
                    .background(BrandRed),
                contentAlignment = Alignment.Center,
            ) {
                Text("胶", color = Color.White, fontWeight = FontWeight.Bold, fontSize = 20.sp)
            }
            Spacer(Modifier.width(10.dp))
            Column(modifier = Modifier.weight(1f)) {
                Text("胶易 AI", color = Ink, fontWeight = FontWeight.Bold, fontSize = 19.sp)
                Text(
                    text = when (localBrainAvailable) {
                        true -> "知己本地大脑已接入"
                        false -> "胶州知识与公交服务"
                        null -> "胶州本地通"
                    },
                    color = if (localBrainAvailable == true) BrandRed else Muted,
                    fontSize = 12.sp,
                )
            }
            if (shareEnabled) {
                TextButton(onClick = onShare) {
                    Text("分享", color = Muted, fontWeight = FontWeight.Medium)
                }
            }
            TextButton(onClick = onNewChat) {
                Text("新对话", color = BrandRed, fontWeight = FontWeight.Medium)
            }
        }
        update?.let {
            Row(
                modifier = Modifier
                    .fillMaxWidth()
                    .background(SoftRed)
                    .clickable { onOpenUpdate(it) }
                    .padding(horizontal = 16.dp, vertical = 8.dp),
                verticalAlignment = Alignment.CenterVertically,
            ) {
                Column(modifier = Modifier.weight(1f)) {
                    Text(
                        "有可选更新 ${it.versionName}",
                        color = DeepRed,
                        fontSize = 13.sp,
                        fontWeight = FontWeight.Bold,
                    )
                    if (it.notes.isNotBlank()) {
                        Text(it.notes, color = Muted, fontSize = 11.sp, maxLines = 1)
                    }
                }
                Text("查看", color = BrandRed, fontSize = 13.sp, fontWeight = FontWeight.Bold)
            }
        }
        HorizontalDivider(color = Line)
    }
}

@Composable
private fun Welcome(
    modifier: Modifier,
    suggestions: List<String>,
    onQuestion: (String) -> Unit,
) {
    Column(
        modifier = modifier
            .fillMaxSize()
            .padding(horizontal = 22.dp),
        horizontalAlignment = Alignment.CenterHorizontally,
        verticalArrangement = Arrangement.Center,
    ) {
        Box(
            modifier = Modifier
                .size(78.dp)
                .clip(RoundedCornerShape(24.dp))
                .background(BrandRed),
            contentAlignment = Alignment.Center,
        ) {
            Text("胶", color = Color.White, fontSize = 40.sp, fontWeight = FontWeight.Bold)
        }
        Spacer(Modifier.height(18.dp))
        Text("泥待奏甚么？", color = Ink, fontSize = 27.sp, fontWeight = FontWeight.Bold)
        Spacer(Modifier.height(8.dp))
        Text(
            "问公交、天气、办事和胶州本地生活",
            color = Muted,
            fontSize = 14.sp,
            textAlign = TextAlign.Center,
        )
        Spacer(Modifier.height(24.dp))
        Column(verticalArrangement = Arrangement.spacedBy(9.dp)) {
            suggestions.take(4).forEach { question ->
                Surface(
                    modifier = Modifier
                        .fillMaxWidth()
                        .clickable { onQuestion(question) },
                    shape = RoundedCornerShape(14.dp),
                    color = Color.White,
                    tonalElevation = 1.dp,
                ) {
                    Text(
                        text = question,
                        modifier = Modifier.padding(horizontal = 16.dp, vertical = 14.dp),
                        color = Ink,
                        fontSize = 15.sp,
                    )
                }
            }
        }
    }
}

@Composable
private fun MessageBubble(
    message: AiMessage,
    contributionEnabled: Boolean,
    onCopy: () -> Unit,
    onContribute: () -> Unit,
) {
    val fromUser = message.role == "user"
    Row(
        modifier = Modifier.fillMaxWidth(),
        horizontalArrangement = if (fromUser) Arrangement.End else Arrangement.Start,
    ) {
        Column(horizontalAlignment = if (fromUser) Alignment.End else Alignment.Start) {
            Surface(
                modifier = Modifier.fillMaxWidth(0.84f),
                shape = RoundedCornerShape(
                    topStart = 18.dp,
                    topEnd = 18.dp,
                    bottomStart = if (fromUser) 18.dp else 5.dp,
                    bottomEnd = if (fromUser) 5.dp else 18.dp,
                ),
                color = if (fromUser) SoftRed else Color.White,
            ) {
                Column(modifier = Modifier.padding(horizontal = 15.dp, vertical = 12.dp)) {
                    Text(
                        text = message.text,
                        color = Ink,
                        fontSize = 16.sp,
                        lineHeight = 24.sp,
                    )
                    if (!fromUser && !message.source.isNullOrBlank()) {
                        Spacer(Modifier.height(7.dp))
                        Text(
                            text = "来源：${message.source}",
                            color = BrandRed,
                            fontSize = 11.sp,
                        )
                    }
                }
            }
            if (!fromUser) {
                Row {
                    TextButton(onClick = onCopy, contentPadding = PaddingValues(horizontal = 6.dp)) {
                        Text("复制", color = Muted, fontSize = 12.sp)
                    }
                    TextButton(
                        onClick = onContribute,
                        enabled = contributionEnabled,
                        contentPadding = PaddingValues(horizontal = 8.dp),
                    ) {
                        Text(
                            "共创补充",
                            color = if (contributionEnabled) BrandRed else Muted,
                            fontSize = 12.sp,
                            fontWeight = FontWeight.Medium,
                        )
                    }
                }
            }
        }
    }
}

@Composable
private fun Composer(
    value: String,
    thinking: Boolean,
    contributing: Boolean,
    notice: String?,
    onValueChange: (String) -> Unit,
    onVoice: () -> Unit,
    onSend: () -> Unit,
    onStop: () -> Unit,
    onCancelContribution: () -> Unit,
) {
    Surface(color = Color.White, shadowElevation = 4.dp) {
        Column(
            modifier = Modifier
                .fillMaxWidth()
                .navigationBarsPadding()
                .imePadding(),
        ) {
            if (contributing) {
                Row(
                    modifier = Modifier
                        .fillMaxWidth()
                        .background(SoftRed)
                        .padding(start = 16.dp, end = 8.dp, top = 8.dp, bottom = 8.dp),
                    verticalAlignment = Alignment.CenterVertically,
                ) {
                    Column(modifier = Modifier.weight(1f)) {
                        Text(
                            "开放共创补充",
                            color = DeepRed,
                            fontSize = 14.sp,
                            fontWeight = FontWeight.Bold,
                        )
                        Text(
                            "不设审核，提交后立即生效",
                            color = Muted,
                            fontSize = 12.sp,
                        )
                    }
                    TextButton(onClick = onCancelContribution) {
                        Text("取消", color = DeepRed)
                    }
                }
            }
            notice?.let {
                Text(
                    text = it,
                    modifier = Modifier
                        .fillMaxWidth()
                        .padding(top = 7.dp, start = 16.dp, end = 16.dp),
                    color = BrandRed,
                    fontSize = 13.sp,
                    textAlign = TextAlign.Center,
                )
            }
            Row(
                modifier = Modifier
                    .fillMaxWidth()
                    .padding(horizontal = 10.dp, vertical = 9.dp),
                verticalAlignment = Alignment.Bottom,
            ) {
                TextButton(
                    onClick = onVoice,
                    enabled = !thinking,
                    modifier = Modifier.size(50.dp),
                    contentPadding = PaddingValues(0.dp),
                ) {
                    Text("语音", color = if (thinking) Muted else BrandRed, fontSize = 13.sp)
                }
                OutlinedTextField(
                    value = value,
                    onValueChange = onValueChange,
                    modifier = Modifier
                        .weight(1f)
                        .heightIn(min = 52.dp, max = 118.dp),
                    placeholder = {
                        Text(
                            if (contributing) "直接补充你的观点或信息…" else "问问胶易…",
                            color = Muted,
                        )
                    },
                    enabled = !thinking,
                    maxLines = 4,
                    shape = RoundedCornerShape(14.dp),
                )
                Spacer(Modifier.width(8.dp))
                if (thinking) {
                    Button(
                        onClick = onStop,
                        modifier = Modifier.height(50.dp),
                        shape = CircleShape,
                        colors = ButtonDefaults.buttonColors(containerColor = Ink),
                        contentPadding = PaddingValues(horizontal = 15.dp),
                    ) {
                        Text("停止", color = Color.White, fontSize = 13.sp)
                    }
                } else {
                    Button(
                        onClick = onSend,
                        enabled = value.isNotBlank(),
                        modifier = Modifier.height(50.dp),
                        shape = CircleShape,
                        colors = ButtonDefaults.buttonColors(containerColor = BrandRed),
                        contentPadding = PaddingValues(horizontal = 17.dp),
                    ) {
                        Text(
                            if (contributing) "提交" else "发送",
                            color = Color.White,
                            fontSize = 14.sp,
                            fontWeight = FontWeight.Bold,
                        )
                    }
                }
            }
        }
    }
}
