package com.tencent.qian.webview.chrome

import android.Manifest
import android.app.Activity
import android.content.Context
import android.net.Uri
import android.webkit.JsResult
import android.webkit.PermissionRequest
import android.webkit.ValueCallback
import android.webkit.WebChromeClient
import android.webkit.WebView
import com.google.android.material.dialog.MaterialAlertDialogBuilder
import com.tencent.qian.webview.filechooser.FileChooserLauncher
import com.tencent.qian.webview.model.SdkEvent
import com.tencent.qian.webview.model.SignCallback
import com.tencent.qian.webview.model.TencentQianWebViewConfig
import com.tencent.qian.webview.permission.RuntimePermissionRequester

/**
 * SDK 内置 WebChromeClient。
 *
 * **职责**:
 * - [onPermissionRequest]:Web 端 getUserMedia 请求 → 系统权限 → grant
 * - [onJsAlert] / [onJsConfirm]:Android 默认会吞掉,SDK 必须实现弹原生窗
 * - [onShowFileChooser]:转 [FileChooserLauncher]
 *
 * **iOS 等价**:`QianUIDelegate.swift`(WKWebView 默认 alert/confirm 自带,只需 media capture grant)。
 */
internal class QianWebChromeClient(
    private val config: TencentQianWebViewConfig,
    private val permissionRequester: RuntimePermissionRequester,
    private val fileChooserLauncher: FileChooserLauncher,
    private val callbackProvider: () -> SignCallback?,
    private val activityProvider: () -> Activity?,
    private val progressListener: ((Int) -> Unit)? = null
) : WebChromeClient() {

    // ────────── 页面加载进度(对应 iOS KVO estimatedProgress) ──────────

    override fun onProgressChanged(view: WebView?, newProgress: Int) {
        progressListener?.invoke(newProgress)
    }

    // ────────── Web 权限 (getUserMedia 等) ──────────

    override fun onPermissionRequest(request: PermissionRequest?) {
        val req = request ?: return
        val activity = activityProvider() ?: run { req.deny(); return }

        // Web 端请求 → 映射 Android runtime 权限
        val androidPerms = req.resources.mapNotNull { webPerm ->
            when (webPerm) {
                PermissionRequest.RESOURCE_VIDEO_CAPTURE -> Manifest.permission.CAMERA
                PermissionRequest.RESOURCE_AUDIO_CAPTURE -> Manifest.permission.RECORD_AUDIO
                else -> null // MIDI / ProtectedMediaId 暂不支持
            }
        }.distinct().toTypedArray()

        if (androidPerms.isEmpty()) {
            req.deny()
            return
        }

        permissionRequester.request(activity, androidPerms) { grants ->
            val allGranted = grants.values.all { it }
            if (allGranted) {
                req.grant(req.resources)
                callbackProvider()?.onEvent(SdkEvent.PermissionGranted(grants.keys.toList()))
            } else {
                req.deny()
                callbackProvider()?.onEvent(
                    SdkEvent.PermissionDenied(
                        grants.filterValues { !it }.keys.toList()
                    )
                )
            }
        }
    }

    // ────────── JS 弹窗 ──────────

    override fun onJsAlert(
        view: WebView?,
        url: String?,
        message: String?,
        result: JsResult?
    ): Boolean {
        val activity = activityProvider()
        // Activity 已销毁或正在 finishing 时,直接 confirm 避免 BadTokenException
        if (activity == null || activity.isFinishing || activity.isDestroyed) {
            result?.confirm()
            return true
        }
        showAlert(activity, message.orEmpty(), positive = activity.getString(com.tencent.qian.webview.R.string.qian_js_ok)) {
            result?.confirm()
        }
        return true
    }

    override fun onJsConfirm(
        view: WebView?,
        url: String?,
        message: String?,
        result: JsResult?
    ): Boolean {
        val activity = activityProvider()
        // Activity 已销毁或正在 finishing 时,直接 cancel 避免 BadTokenException
        if (activity == null || activity.isFinishing || activity.isDestroyed) {
            result?.cancel()
            return true
        }
        showConfirm(
            activity,
            message.orEmpty(),
            onPositive = { result?.confirm() },
            onNegative = { result?.cancel() }
        )
        return true
    }

    // ────────── 文件选择 ──────────

    override fun onShowFileChooser(
        webView: WebView?,
        filePathCallback: ValueCallback<Array<Uri>>?,
        fileChooserParams: FileChooserParams?
    ): Boolean {
        val params = fileChooserParams ?: return false
        return fileChooserLauncher.launch(
            params = params,
            filePathCallback = filePathCallback,
            legacyFaceCaptureMimeTypes = config.legacyFaceCaptureMimeTypes,
            cameraCaptureBehavior = config.cameraCaptureBehavior
        )
    }

    // ────────── 私有 dialog 渲染 ──────────

    private fun showAlert(ctx: Context, message: String, positive: String, onPositive: () -> Unit) {
        try {
            when (config.jsDialogStyle) {
                TencentQianWebViewConfig.JsDialogStyle.MATERIAL ->
                    MaterialAlertDialogBuilder(ctx)
                        .setMessage(message)
                        .setPositiveButton(positive) { d, _ -> d.dismiss(); onPositive() }
                        .setOnCancelListener { onPositive() }
                        .setCancelable(true)
                        .show()
                TencentQianWebViewConfig.JsDialogStyle.SYSTEM ->
                    android.app.AlertDialog.Builder(ctx)
                        .setMessage(message)
                        .setPositiveButton(positive) { d, _ -> d.dismiss(); onPositive() }
                        .setOnCancelListener { onPositive() }
                        .setCancelable(true)
                        .show()
            }
        } catch (_: android.view.WindowManager.BadTokenException) {
            // Activity 窗口已失效(OEM 设备销毁动画期间仍可能触发),静默回调
            onPositive()
        }
    }

    private fun showConfirm(
        ctx: Context,
        message: String,
        onPositive: () -> Unit,
        onNegative: () -> Unit
    ) {
        try {
            when (config.jsDialogStyle) {
                TencentQianWebViewConfig.JsDialogStyle.MATERIAL ->
                    MaterialAlertDialogBuilder(ctx)
                        .setMessage(message)
                        .setPositiveButton(ctx.getString(com.tencent.qian.webview.R.string.qian_js_ok)) { d, _ -> d.dismiss(); onPositive() }
                        .setNegativeButton(ctx.getString(com.tencent.qian.webview.R.string.qian_js_cancel)) { d, _ -> d.dismiss(); onNegative() }
                        .setOnCancelListener { onNegative() }
                        .setCancelable(true)
                        .show()
                TencentQianWebViewConfig.JsDialogStyle.SYSTEM ->
                    android.app.AlertDialog.Builder(ctx)
                        .setMessage(message)
                        .setPositiveButton(ctx.getString(com.tencent.qian.webview.R.string.qian_js_ok)) { d, _ -> d.dismiss(); onPositive() }
                        .setNegativeButton(ctx.getString(com.tencent.qian.webview.R.string.qian_js_cancel)) { d, _ -> d.dismiss(); onNegative() }
                        .setOnCancelListener { onNegative() }
                        .setCancelable(true)
                        .show()
            }
        } catch (_: android.view.WindowManager.BadTokenException) {
            // Activity 窗口已失效(OEM 设备销毁动画期间仍可能触发),静默回调
            onNegative()
        }
    }
}
