/**
 * Cloudflare 挑战统一处理：检测 → 内置等待 → Captcha API 兜底
 */
const { detectCloudflare } = require('./cf-detector');
const { waitForTurnstile, extractTurnstileSitekey, injectTurnstileToken } = require('./turnstile-handler');
const { solveTurnstile, isCaptchaConfigured } = require('./captcha-solver');

/**
 * @typedef {Object} CfHandleResult
 * @property {boolean} success
 * @property {string|null} code
 * @property {string|null} challengeType
 * @property {string|null} stage
 * @property {boolean} solverUsed
 * @property {number} elapsedMs
 * @property {boolean} cfDetected
 */

/**
 * 处理 Cloudflare / Turnstile 挑战（在 authActions 之前调用）
 * @param {import('puppeteer').Page} page
 * @param {{ turnstile?: boolean, solverFallback?: boolean, challengeTimeoutMs?: number }} antiBot
 * @param {(page: import('puppeteer').Page) => Promise<string>} [waitForUrlSettled]
 * @returns {Promise<CfHandleResult>}
 */
async function handleCloudflareChallenge(page, antiBot, waitForUrlSettled) {
    const started = Date.now();
    const timeoutMs = antiBot.challengeTimeoutMs || 60000;

    let cfState = await detectCloudflare(page);
    if (!cfState.blocked) {
        return {
            success: true,
            code: null,
            challengeType: null,
            stage: null,
            solverUsed: false,
            elapsedMs: Date.now() - started,
            cfDetected: false,
        };
    }

    console.log(`[CF] 检测到挑战 type=${cfState.challengeType} url=${cfState.url}`);

    if (antiBot.turnstile !== false) {
        const builtIn = await waitForTurnstile(page, { timeoutMs, useBuiltInClick: true });
        if (builtIn.success) {
            if (waitForUrlSettled) {
                await waitForUrlSettled(page).catch(() => {});
            }
            cfState = await detectCloudflare(page);
            if (!cfState.blocked) {
                return {
                    success: true,
                    code: null,
                    challengeType: cfState.challengeType,
                    stage: 'built_in',
                    solverUsed: false,
                    elapsedMs: Date.now() - started,
                    cfDetected: true,
                };
            }
        }
    }

    if (antiBot.solverFallback !== false && isCaptchaConfigured()) {
        try {
            const sitekey = await extractTurnstileSitekey(page);
            const pageUrl = page.url();
            const { token, provider } = await solveTurnstile({ pageUrl, sitekey });
            console.log(`[CF] Captcha API (${provider}) 返回 token，注入页面`);
            await injectTurnstileToken(page, token);

            const apiWaitMs = Math.min(timeoutMs, 30000);
            await waitForTurnstile(page, { timeoutMs: apiWaitMs });

            if (waitForUrlSettled) {
                await waitForUrlSettled(page).catch(() => {});
            }

            cfState = await detectCloudflare(page);
            if (!cfState.blocked) {
                return {
                    success: true,
                    code: null,
                    challengeType: 'turnstile',
                    stage: 'api',
                    solverUsed: true,
                    elapsedMs: Date.now() - started,
                    cfDetected: true,
                };
            }
        } catch (apiErr) {
            console.error('[CF] Captcha API 兜底失败:', apiErr.message);
            return {
                success: false,
                code: 'CF_TURNSTILE_FAILED',
                challengeType: cfState.challengeType || 'turnstile',
                stage: 'api',
                solverUsed: true,
                elapsedMs: Date.now() - started,
                cfDetected: true,
            };
        }
    }

    return {
        success: false,
        code: 'CF_TURNSTILE_FAILED',
        challengeType: cfState.challengeType || 'unknown',
        stage: antiBot.solverFallback !== false && !isCaptchaConfigured() ? 'built_in' : 'timeout',
        solverUsed: false,
        elapsedMs: Date.now() - started,
        cfDetected: true,
    };
}

module.exports = {
    handleCloudflareChallenge,
    isCaptchaConfigured,
};
