package com.tencent.qian.webview.prewarm;

import static org.junit.Assert.assertNotNull;
import static org.junit.Assert.assertNull;
import static org.junit.Assert.assertSame;
import static org.junit.Assert.assertTrue;

import android.content.Context;
import android.os.Build;
import android.webkit.WebView;
import android.webkit.WebViewClient;

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.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;

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

    private Context appContext;

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

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

    @Test
    public void invalidateIfPooled_hitCurrentPooled_destroysAndClears() {
        WebView pooled = preCreateAndReturnToPool();

        WebViewPool.invalidateIfPooled(pooled);

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

    @Test
    public void invalidateIfPooled_nonPoolInstance_leavesPoolIntact() {
        WebView pooled = preCreateAndReturnToPool();

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

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

    @Test
    public void invalidateIfPooled_null_leavesPoolIntact() {
        WebView pooled = preCreateAndReturnToPool();

        WebViewPool.invalidateIfPooled(null);

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

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

    @Test
    public void poolGuardClient_onRenderProcessGone_returnsTrueAndInvalidatesPool() {
        WebView pooled = preCreateAndReturnToPool();

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

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

    @Test
    public void poolGuardClient_onRenderProcessGone_nonPoolInstance_doesNotInvalidate() {
        WebView pooled = preCreateAndReturnToPool();

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

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

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

    @Test
    public void fallbackClient_onRenderProcessGone_returnsTrueAndInvalidatesPool() {
        WebView pooled = preCreateAndReturnToPool();

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

        WebViewClient fallback = Shadows.shadowOf(pooled).getWebViewClient();
        boolean result = fallback.onRenderProcessGone(pooled, null);

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

        activityController.destroy();
    }

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

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