package com.tencent.qian.webview.scheme

import android.content.ActivityNotFoundException
import android.content.Context
import android.content.Intent
import android.net.Uri
import android.util.Log
import com.tencent.qian.webview.model.SdkEvent
import com.tencent.qian.webview.model.SignCallback

/**
 * 外部 scheme(微信 / 支付宝 / 自定义)处理器。
 *
 * **职责**:
 * - 识别 URL scheme 是否在 `externalSchemes` 白名单
 * - 调 `Intent.ACTION_VIEW` 启动外部 App
 * - 失败(无目标 Activity)时发 [SdkEvent.SchemeNotMatched] 事件
 *
 * **覆盖语义**:`externalSchemes` 由调用方(SDK 内部)直接传入,本类不做默认值;默认值在
 * [com.tencent.qian.webview.model.TencentQianWebViewConfig.externalSchemes]。
 *
 * **Android 11+ (API 30) Package Visibility 注意事项**:
 * 自 Android 11 起,系统对 `startActivity` 的 Intent 解析施加了包可见性限制。
 * 客户在自定义 `externalSchemes` 时(如添加 `mqqapi`、`tbopen` 等),**必须**在其
 * `AndroidManifest.xml` 中声明对应的 `<queries>` 条目,否则 `startActivity` 会抛
 * `ActivityNotFoundException`(即使目标 App 已安装)。示例:
 * ```xml
 * <queries>
 *     <intent>
 *         <action android:name="android.intent.action.VIEW" />
 *         <data android:scheme="weixin" />
 *     </intent>
 *     <intent>
 *         <action android:name="android.intent.action.VIEW" />
 *         <data android:scheme="alipays" />
 *     </intent>
 * </queries>
 * ```
 * SDK 默认的 `weixin` / `alipays` 已在 Demo 的 Manifest 中声明;客户扩展时需自行补充。
 */
internal class ExternalSchemeHandler(
    private val externalSchemes: List<String>,
    private val callbackProvider: () -> SignCallback?
) {

    /**
     * 尝试启动外部 App。
     *
     * @return `true` 已识别(无论启动成功失败均消费此次导航),`false` 未识别
     */
    fun tryStartActivity(context: Context, urlString: String?): Boolean {
        if (urlString.isNullOrEmpty()) return false
        val uri = runCatching { Uri.parse(urlString) }.getOrNull() ?: return false
        val scheme = uri.scheme?.lowercase() ?: return false

        // http(s) 不归本 handler 处理
        if (scheme == "http" || scheme == "https") return false
        // qianapp 优先级最高,不会走到这里;防御性兜底
        if (scheme == "qianapp") return false

        val matched = externalSchemes.any { it.equals(scheme, ignoreCase = true) }
        if (!matched) {
            // 未匹配 → 发事件 + 丢弃,WebView 不应继续加载未知 scheme
            callbackProvider()?.onEvent(SdkEvent.SchemeNotMatched(urlString))
            return true
        }

        return try {
            val intent = Intent(Intent.ACTION_VIEW, uri).apply {
                addFlags(Intent.FLAG_ACTIVITY_NEW_TASK)
            }
            context.startActivity(intent)
            callbackProvider()?.onEvent(SdkEvent.SchemeIntercepted(scheme = scheme, url = urlString))
            true
        } catch (e: ActivityNotFoundException) {
            Log.w(TAG, "no Activity for scheme=$scheme url=$urlString", e)
            callbackProvider()?.onEvent(SdkEvent.SchemeNotMatched(urlString))
            true
        } catch (e: SecurityException) {
            Log.w(TAG, "security denied scheme=$scheme url=$urlString", e)
            callbackProvider()?.onEvent(SdkEvent.SchemeNotMatched(urlString))
            true
        }
    }

    private companion object {
        const val TAG = "QianExternalScheme"
    }
}
