package app.dudu.app

import android.content.Context
import android.graphics.Bitmap
import android.graphics.BitmapFactory
import android.net.Uri
import android.os.Build
import androidx.activity.compose.rememberLauncherForActivityResult
import androidx.activity.result.PickVisualMediaRequest
import androidx.activity.result.contract.ActivityResultContracts
import androidx.compose.foundation.Image
import androidx.compose.foundation.background
import androidx.compose.foundation.clickable
import androidx.compose.foundation.interaction.MutableInteractionSource
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.offset
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.size
import androidx.compose.foundation.layout.systemBarsPadding
import androidx.compose.foundation.rememberScrollState
import androidx.compose.foundation.shape.CircleShape
import androidx.compose.foundation.shape.RoundedCornerShape
import androidx.compose.foundation.text.BasicTextField
import androidx.compose.foundation.verticalScroll
import androidx.compose.runtime.Composable
import androidx.compose.runtime.collectAsState
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.geometry.CornerRadius
import androidx.compose.ui.graphics.PathEffect
import androidx.compose.ui.graphics.SolidColor
import androidx.compose.ui.graphics.asImageBitmap
import androidx.compose.ui.graphics.drawscope.Stroke
import androidx.compose.ui.draw.drawBehind
import androidx.compose.ui.layout.ContentScale
import androidx.compose.ui.platform.LocalContext
import androidx.compose.ui.text.TextStyle
import androidx.compose.ui.text.font.FontWeight
import androidx.compose.ui.unit.dp
import androidx.compose.ui.unit.sp
import app.dudu.BuildConfig
import app.dudu.data.AccountRepository
import app.dudu.design.DText
import app.dudu.design.IconPlus
import app.dudu.design.IconX
import app.dudu.design.LocalDuduPalette
import app.dudu.net.ApiException
import app.dudu.net.DuduApi
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.launch
import kotlinx.coroutines.withContext
import org.json.JSONObject

private const val MAX_CONTENT = 1000      // protocol.FeedbackMaxContentLen
private const val MAX_IMAGES = 3          // protocol.FeedbackMaxImages
private const val MAX_IMAGE_BYTES = 5 shl 20 // protocol.FeedbackMaxImageBytes = 5MB

/** 已选图片：原始字节 + 缩略图。 */
private class PickedImage(val bytes: ByteArray, val thumb: Bitmap)

/**
 * 反馈页（13F）：多行文本（1-1000 计数）+ 图片 ≤3 张 ≤5MB（PhotoPicker）+
 * 诊断信息开关 + multipart POST /v1/feedback；成功态"已收到 · 谢谢你"。
 */
@Composable
fun FeedbackScreen(onBack: () -> Unit) {
    val p = LocalDuduPalette.current
    val context = LocalContext.current
    val repo = remember { AccountRepository.get(context) }
    val account by repo.snapshot.collectAsState()
    val scope = rememberCoroutineScope()

    var content by remember { mutableStateOf("") }
    var images by remember { mutableStateOf(listOf<PickedImage>()) }
    var withDiagnostics by remember { mutableStateOf(true) }
    var submitting by remember { mutableStateOf(false) }
    var done by remember { mutableStateOf(false) }
    var error by remember { mutableStateOf<String?>(null) }

    val picker = rememberLauncherForActivityResult(
        ActivityResultContracts.PickMultipleVisualMedia(MAX_IMAGES),
    ) { uris ->
        if (uris.isEmpty()) return@rememberLauncherForActivityResult
        scope.launch {
            val room = MAX_IMAGES - images.size
            var oversize = false
            val loaded = withContext(Dispatchers.IO) {
                uris.take(room).mapNotNull { uri ->
                    val bytes = readBytes(context, uri) ?: return@mapNotNull null
                    if (bytes.size > MAX_IMAGE_BYTES) {
                        oversize = true
                        return@mapNotNull null
                    }
                    decodeThumb(bytes)?.let { PickedImage(bytes, it) }
                }
            }
            images = images + loaded
            error = if (oversize) "单张图片需小于 5MB" else null
        }
    }

    fun submit() {
        val token = account.token ?: run { error = "请先登录"; return }
        if (submitting || content.isBlank()) return
        submitting = true
        error = null
        scope.launch {
            try {
                val diag = if (withDiagnostics) diagnosticsJson(context) else null
                DuduApi.submitFeedback(
                    token = token,
                    content = content.trim(),
                    images = images.map { it.bytes },
                    diagnostics = diag,
                )
                done = true
            } catch (e: ApiException) {
                error = if (e.code == "FEEDBACK_RATE_LIMITED") "今天反馈次数已达上限" else e.message
            } finally {
                submitting = false
            }
        }
    }

    Column(
        Modifier
            .fillMaxSize()
            .background(p.bgApp)
            .systemBarsPadding()
            .verticalScroll(rememberScrollState())
            .padding(horizontal = 24.dp),
    ) {
        TopBar("反馈问题", onBack)
        VSpace(8)

        if (done) {
            // ── 成功态 ──
            VSpace(64)
            Column(Modifier.fillMaxWidth(), horizontalAlignment = Alignment.CenterHorizontally) {
                SuccessCheckCircle()
                VSpace(16)
                DText("已收到 · 谢谢你", 17.sp, p.text1, weight = FontWeight.SemiBold)
                VSpace(28)
                GhostButton("继续反馈") {
                    content = ""
                    images = emptyList()
                    done = false
                }
                VSpace(12)
                GhostButton("返回", onClick = onBack)
            }
            VSpace(40)
            return@Column
        }

        // ── 文本输入 ──
        DCard {
            BasicTextField(
                value = content,
                onValueChange = { if (it.length <= MAX_CONTENT) content = it },
                modifier = Modifier
                    .fillMaxWidth()
                    .height(140.dp),
                textStyle = TextStyle(color = p.text1, fontSize = 15.sp, lineHeight = 22.sp),
                cursorBrush = SolidColor(p.accent),
                decorationBox = { inner ->
                    Box {
                        if (content.isEmpty()) {
                            DText("说说遇到的问题或建议", 15.sp, p.text3)
                        }
                        inner()
                    }
                },
            )
            Row(Modifier.fillMaxWidth()) {
                Spacer(Modifier.weight(1f))
                DText("${content.length} / $MAX_CONTENT", 12.sp, p.text3, mono = true)
            }
        }
        VSpace(12)

        // ── 图片 ──
        Row(horizontalArrangement = Arrangement.spacedBy(10.dp)) {
            images.forEachIndexed { i, img ->
                Box {
                    Image(
                        bitmap = img.thumb.asImageBitmap(),
                        contentDescription = null,
                        contentScale = ContentScale.Crop,
                        modifier = Modifier
                            .size(64.dp)
                            .clip(RoundedCornerShape(6.dp)),
                    )
                    val src = remember { MutableInteractionSource() }
                    Box(
                        Modifier
                            .size(20.dp)
                            .align(Alignment.TopEnd)
                            .offset(x = 6.dp, y = (-6).dp)
                            .clip(CircleShape)
                            .background(p.overlayBg)
                            .clickable(interactionSource = src, indication = null) {
                                images = images.filterIndexed { idx, _ -> idx != i }
                            },
                        contentAlignment = Alignment.Center,
                    ) {
                        IconX(10.dp, p.overlayText)
                    }
                }
            }
            if (images.size < MAX_IMAGES) {
                val src = remember { MutableInteractionSource() }
                val borderColor = p.border2
                Box(
                    Modifier
                        .size(64.dp)
                        .clip(RoundedCornerShape(6.dp))
                        .drawBehind {
                            drawRoundRect(
                                color = borderColor,
                                cornerRadius = CornerRadius(6.dp.toPx()),
                                style = Stroke(
                                    width = 2.dp.toPx(),
                                    pathEffect = PathEffect.dashPathEffect(floatArrayOf(8f, 8f)),
                                ),
                            )
                        }
                        .clickable(interactionSource = src, indication = null) {
                            picker.launch(
                                PickVisualMediaRequest(ActivityResultContracts.PickVisualMedia.ImageOnly),
                            )
                        },
                    contentAlignment = Alignment.Center,
                ) {
                    IconPlus(20.dp, p.text3)
                }
            }
        }
        VSpace(6)
        DText("最多 3 张 · 单张 5MB 以内", 12.sp, p.text3)
        VSpace(16)

        // ── 诊断信息开关 ──
        DCard {
            Row(verticalAlignment = Alignment.CenterVertically) {
                Column(Modifier.weight(1f)) {
                    DText("附带诊断信息", 14.sp, p.text1)
                    VSpace(3)
                    DText("版本、系统、设备型号", 12.sp, p.text3)
                }
                DSwitch(withDiagnostics) { withDiagnostics = !withDiagnostics }
            }
        }

        NoticeText(error)
        VSpace(20)

        PrimaryButton(
            "提交",
            enabled = content.isNotBlank(),
            loading = submitting,
        ) { submit() }
        VSpace(40)
    }
}

// ─── 工具 ────────────────────────────────────────────────────────────────────

private fun readBytes(context: Context, uri: Uri): ByteArray? =
    runCatching {
        context.contentResolver.openInputStream(uri)?.use { it.readBytes() }
    }.getOrNull()

/** 缩略图：inSampleSize 解到 ~128px，避免大图占内存。 */
private fun decodeThumb(bytes: ByteArray): Bitmap? {
    val bounds = BitmapFactory.Options().apply { inJustDecodeBounds = true }
    BitmapFactory.decodeByteArray(bytes, 0, bytes.size, bounds)
    if (bounds.outWidth <= 0 || bounds.outHeight <= 0) return null
    var sample = 1
    while (bounds.outWidth / (sample * 2) >= 128 && bounds.outHeight / (sample * 2) >= 128) sample *= 2
    val opts = BitmapFactory.Options().apply { inSampleSize = sample }
    return BitmapFactory.decodeByteArray(bytes, 0, bytes.size, opts)
}

/** 诊断信息（不含识别文本）：app 版本 / Android 版本 / 设备型号 / device_id。 */
private fun diagnosticsJson(context: Context): String =
    JSONObject()
        .put("platform", "android")
        .put("app_version", BuildConfig.VERSION_NAME)
        .put("os_version", "Android " + Build.VERSION.RELEASE)
        .put("device_model", Build.MANUFACTURER + " " + Build.MODEL)
        .put("device_id", AccountRepository.get(context).deviceId)
        .toString()
