package com.tencent.qian.webview.prewarm

import android.content.Context
import android.os.Build
import android.webkit.WebView
import androidx.activity.ComponentActivity
import androidx.test.ext.junit.runners.AndroidJUnit4
import com.tencent.qian.webview.TencentQianWebViewConfigurator
import com.tencent.qian.webview.model.TencentQianWebViewConfig
import org.junit.Assert.assertNotNull
import org.junit.Assert.assertNull
import org.junit.Assert.assertSame
import org.junit.Assert.assertTrue
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.robolectric.Robolectric
import org.robolectric.RuntimeEnvironment
import org.robolectric.Shadows
import org.robolectric.android.controller.ActivityController
import org.robolectric.annotation.Config

/**
 * 渲染进程崩溃恢复相关单测。
 *
 * 覆盖 fix(android) 的三态 onRenderProcessGone 闭环：
 * - [WebViewPool.invalidateIfPooled]：作废逻辑（命中 / 非池实例 / null）
 * - PoolGuardClient.onRenderProcessGone：预热态守卫 → 返回 true + 作废池
 * - QianFallbackWebViewClient.onRenderProcessGone：归还态兜底 → 返回 true + 作废池
 *
 * 与 Java 版 WebViewPoolRenderProcessGoneTest 同一组用例。
 */
@RunWith(AndroidJUnit4::class)
@Config(sdk = [Build.VERSION_CODES.O])
class WebViewPoolRenderProcessGoneTest {

    private lateinit var appContext: Context

    @Before
    fun setUp() {
        appContext = RuntimeEnvironment.getApplication()
        // 每个测试前重置池状态（销毁可能残留的池实例 + 清空 inUse / uaSig 等）
        WebViewPool.release()
    }

    // ────────── invalidateIfPooled ──────────

    @Test
    fun invalidateIfPooled_hitCurrentPooled_destroysAndClears() {
        val pooled = preCreateAndReturnToPool()

        WebViewPool.invalidateIfPooled(pooled)

        // 池已空：再 obtain 返回 null
        assertNull(WebViewPool.obtain(appContext, false, ""))
    }

    @Test
    fun invalidateIfPooled_nonPoolInstance_leavesPoolIntact() {
        val pooled = preCreateAndReturnToPool()

        // 传入一个不同的 WebView 实例 → 不应作废池
        val other = WebView(appContext)
        WebViewPool.invalidateIfPooled(other)

        // 池不变：再 obtain 仍能拿到原实例
        val again = WebViewPool.obtain(appContext, false, "")
        assertNotNull(again)
        assertSame(pooled, again)
    }

    @Test
    fun invalidateIfPooled_null_leavesPoolIntact() {
        val pooled = preCreateAndReturnToPool()

        WebViewPool.invalidateIfPooled(null)

        // 池不变
        val again = WebViewPool.obtain(appContext, false, "")
        assertNotNull(again)
        assertSame(pooled, again)
    }

    // ────────── PoolGuardClient（预热态守卫）──────────

    @Test
    fun poolGuardClient_onRenderProcessGone_returnsTrueAndInvalidatesPool() {
        val pooled = preCreateAndReturnToPool()

        // 池实例创建时挂了 PoolGuardClient（ensureInstance 中 setWebViewClient）
        val guard = Shadows.shadowOf(pooled).webViewClient
        val result = guard.onRenderProcessGone(pooled, null)

        assertTrue(result)
        // 池被作废
        assertNull(WebViewPool.obtain(appContext, false, ""))
    }

    @Test
    fun poolGuardClient_onRenderProcessGone_nonPoolInstance_doesNotInvalidate() {
        val pooled = preCreateAndReturnToPool()

        val guard = Shadows.shadowOf(pooled).webViewClient
        // 传入非池实例 → 返回 true（保进程）但不作废池
        val other = WebView(appContext)
        val result = guard.onRenderProcessGone(other, null)

        assertTrue(result)
        // 池不变
        val again = WebViewPool.obtain(appContext, false, "")
        assertNotNull(again)
        assertSame(pooled, again)
    }

    // ────────── QianFallbackWebViewClient（归还态兜底）──────────

    @Test
    fun fallbackClient_onRenderProcessGone_returnsTrueAndInvalidatesPool() {
        val pooled = preCreateAndReturnToPool()

        // 模拟真实归还流程：Configurator.apply 注入 SDK client → detach 切换到 QianFallbackWebViewClient
        val activityController = Robolectric.buildActivity(ComponentActivity::class.java)
        val activity = activityController.get()
        // apply 内部 registerForActivityResult，必须在 create() 之前调用
        val handle = TencentQianWebViewConfigurator.apply(
            activity = activity,
            webView = pooled,
            config = TencentQianWebViewConfig.DEFAULT,
            callback = null
        )
        activityController.create()
        handle.detach()

        val fallback = Shadows.shadowOf(pooled).webViewClient
        val result = fallback.onRenderProcessGone(pooled, null)

        assertTrue(result)
        // 池被作废
        assertNull(WebViewPool.obtain(appContext, false, ""))

        activityController.destroy()
    }

    // ────────── 辅助 ──────────

    /**
     * 预建池实例并归还（池中有实例，inUse=false）。
     * 返回池实例引用，供后续 invalidate / onRenderProcessGone 测试使用。
     */
    private fun preCreateAndReturnToPool(): WebView {
        WebViewPool.preCreate(appContext, false, "")
        val pooled = WebViewPool.obtain(appContext, false, "")
        assertNotNull("preCreate should create a pooled instance", pooled)
        WebViewPool.recycle(pooled!!)
        return pooled
    }
}
