/**
 * CapSolver / 2Captcha 过盾兜底：Turnstile token 注入 或 AntiCloudflareTask cf_clearance
 *
 * A2C 等业务域为 CF Managed Challenge（非独立 Turnstile 挂件），须优先 AntiCloudflareTask。
 */
const { sanitizePageUrlForCfSolver } = require('./cf-detector');
const {
    injectTurnstileToken,
    recoverAfterTokenInject,
    extractTurnstileSitekey,
} = require('./turnstile-handler');
const {
    solveTurnstile,
    solveCloudflare,
    applyCfClearanceSolution,
} = require('./captcha-solver');
const { getSitekeyCapture } = require('./sitekey-capture');

/** @returns {boolean} */
function hasCaptchaProxy() {
    return (process.env.CAPTCHA_PROXY || '').trim() !== '';
}

/**
 * 是否应使用 CapSolver AntiCloudflareTask（Managed Challenge / 5s 盾）
 * @param {object|null|undefined} antiBot
 */
function shouldPreferManagedCloudflareSolver(antiBot) {
    if (!antiBot || antiBot.cfCloudflareSolver === false) {
        return false;
    }
    if (antiBot.cfChallengeMode === 'managed') {
        return hasCaptchaProxy();
    }
    if (antiBot.cfCloudflareSolver === true && hasCaptchaProxy()) {
        return true;
    }
    return false;
}

/**
 * 解析可用于 AntiTurnstileTask 的 sitekey（排除 A2C 配置的 challenge sitekey）
 * @param {import('puppeteer').Page} page
 * @param {object} antiBot
 * @param {number} waitMs
 * @returns {Promise<string|null>}
 */
async function resolveTurnstileWidgetSitekey(page, antiBot, waitMs) {
    if (antiBot.cfChallengeMode === 'managed') {
        return null;
    }

    const capture = getSitekeyCapture(page);
    if (capture) {
        const fromCapture = await capture.resolveForSolver(page, antiBot, waitMs);
        if (fromCapture && antiBot.cfChallengeMode !== 'managed') {
            const configured = String(antiBot.turnstileSitekey || '').trim();
            if (configured && fromCapture === configured && antiBot.cfCloudflareSolver) {
                return null;
            }
            return fromCapture;
        }
    }

    const dynamic = await extractTurnstileSitekey(page);
    if (dynamic) {
        return dynamic;
    }

    const configured = String(antiBot?.turnstileSitekey || '').trim();
    if (configured && !antiBot.cfCloudflareSolver) {
        return configured;
    }

    return null;
}

/**
 * CapSolver AntiCloudflareTask 求解并注入 cf_clearance
 * @param {import('puppeteer').Page} page
 * @param {object} params
 */
async function runManagedCloudflareSolver(page, params) {
    const { cleanSolverUrl, waitForUrlSettled, timeoutMs } = params;

    if (!hasCaptchaProxy()) {
        throw new Error('AntiCloudflareTask 需要配置 CAPTCHA_PROXY（静态代理 ip:port:user:pass）');
    }

    console.log('[CF] A2C/Managed Challenge：使用 CapSolver AntiCloudflareTask');
    const html = await page.content().catch(() => '');
    const userAgent = await page.evaluate(() => navigator.userAgent).catch(() => '');
    const { cookies, userAgent: solvedUa, provider } = await solveCloudflare({
        pageUrl: cleanSolverUrl,
        html,
        userAgent,
    });
    console.log(`[CF] CapSolver AntiCloudflareTask (${provider}) 返回 cf_clearance`);
    await applyCfClearanceSolution(page, cleanSolverUrl, { cookies, userAgent: solvedUa || userAgent });
    if (typeof waitForUrlSettled === 'function') {
        await waitForUrlSettled(page).catch(() => {});
    }

    return { mode: 'cloudflare', provider };
}

/**
 * @param {import('puppeteer').Page} page
 * @param {object} options
 * @param {object} options.antiBot
 * @param {string} [options.navUrl]
 * @param {(page: import('puppeteer').Page) => Promise<string>} [options.waitForUrlSettled]
 * @param {number} [options.timeoutMs]
 * @returns {Promise<{ mode: 'turnstile'|'cloudflare', provider: string }>}
 */
async function runCaptchaApiFallback(page, options) {
    const {
        antiBot,
        navUrl = '',
        waitForUrlSettled,
        timeoutMs = 60000,
    } = options;

    const cleanSolverUrl = sanitizePageUrlForCfSolver(navUrl || page.url());

    if (shouldPreferManagedCloudflareSolver(antiBot)) {
        console.log(`[CF] Captcha API 求解 pageUrl=${cleanSolverUrl} mode=managed_challenge`);
        return runManagedCloudflareSolver(page, { cleanSolverUrl, waitForUrlSettled, timeoutMs });
    }

    const sitekey = await resolveTurnstileWidgetSitekey(
        page,
        antiBot,
        Math.min(timeoutMs, 25000)
    );
    console.log(`[CF] Captcha API 求解 pageUrl=${cleanSolverUrl} sitekey=${sitekey ? 'ok' : 'missing'}`);

    if (sitekey) {
        try {
            const { token, provider } = await solveTurnstile({ pageUrl: cleanSolverUrl, sitekey });
            console.log(`[CF] Captcha API Turnstile (${provider}) 返回 token，注入页面`);
            await injectTurnstileToken(page, token);
            await recoverAfterTokenInject(
                page,
                cleanSolverUrl,
                waitForUrlSettled,
                Math.min(timeoutMs, 45000)
            );
            return { mode: 'turnstile', provider };
        } catch (turnstileErr) {
            const msg = (turnstileErr?.message || '').toLowerCase();
            const isChallengeMismatch = msg.includes('challenge, not turnstile')
                || msg.includes('not turnstile');
            if (isChallengeMismatch && antiBot.cfCloudflareSolver !== false && hasCaptchaProxy()) {
                console.warn(`[CF] Turnstile 任务失败(${turnstileErr.message})，降级 AntiCloudflareTask`);
                return runManagedCloudflareSolver(page, { cleanSolverUrl, waitForUrlSettled, timeoutMs });
            }
            throw turnstileErr;
        }
    }

    if (antiBot?.cfCloudflareSolver !== false && hasCaptchaProxy()) {
        return runManagedCloudflareSolver(page, { cleanSolverUrl, waitForUrlSettled, timeoutMs });
    }

    throw new Error('无法过盾：请配置 CAPTCHA_PROXY（A2C Managed Challenge）或提供有效 Turnstile sitekey');
}

module.exports = {
    runCaptchaApiFallback,
    shouldPreferManagedCloudflareSolver,
    hasCaptchaProxy,
};
