/**
 * Cloudflare / Turnstile 挑战页检测
 *
 * antiBot.cfClearanceRequired === false（A2C 业务域）：仅真实 CF 中间页算 blocked，
 * 不因页面引用 turnstile.js 或缺少 cf_clearance cookie 误判。
 */

/**
 * URL 是否处于 CF Managed Challenge 中间态（Whatshub 短链常见 __cf_chl_rt_tk）
 * @param {string} url
 */
function urlIndicatesCfChallenge(url) {
    if (!url || typeof url !== 'string') {
        return false;
    }
    return url.includes('__cf_chl_rt_tk')
        || url.includes('__cf_chl_tk')
        || url.includes('__cf_chl_f_tk')
        || url.includes('/cdn-cgi/challenge-platform')
        || url.includes('/cdn-cgi/challenge');
}

/** CF 挑战态查询参数（CapSolver websiteURL 需剔除） */
const CF_CHALLENGE_QUERY_KEYS = [
    '__cf_chl_rt_tk',
    '__cf_chl_tk',
    '__cf_chl_f_tk',
    '__cf_chl_captcha_tk__',
];

/**
 * 去掉 URL 中 CF 挑战临时参数，供 CapSolver / reload 使用
 * @param {string} url
 * @returns {string}
 */
function sanitizePageUrlForCfSolver(url) {
    if (!url || typeof url !== 'string') {
        return url || '';
    }
    try {
        const parsed = new URL(url);
        for (const key of CF_CHALLENGE_QUERY_KEYS) {
            parsed.searchParams.delete(key);
        }
        return parsed.toString();
    } catch (_) {
        return url.split('?')[0] || url;
    }
}

/**
 * 是否要求 cf_clearance 才视为过盾完成（A2C user.a2c.chat 为 false）
 * @param {object|null|undefined} antiBot
 */
function isCfClearanceRequired(antiBot) {
    return antiBot?.cfClearanceRequired !== false;
}

/**
 * @typedef {Object} CloudflareState
 * @property {boolean} blocked 是否处于 CF 挑战中
 * @property {string|null} challengeType turnstile|js_challenge|unknown|null
 * @property {boolean} hasCfClearance 是否已有 cf_clearance cookie
 * @property {string} url 当前页面 URL
 * @property {string} title 页面 title
 */

/**
 * 检测页面是否被 Cloudflare 拦截
 * @param {import('puppeteer').Page} page
 * @param {object|null} [antiBot]
 * @returns {Promise<CloudflareState>}
 */
async function detectCloudflare(page, antiBot = null) {
    const url = page.url();
    const title = await page.title().catch(() => '');

    const cookies = await page.cookies().catch(() => []);
    const hasCfClearance = cookies.some((c) => c.name === 'cf_clearance');

    const domSignals = await page.evaluate(() => {
        const hasTurnstileInput = !!document.querySelector('[name="cf-turnstile-response"]');
        const hasTurnstileWidget = !!document.querySelector('.cf-turnstile, [data-sitekey]');
        const hasChallengeRunning = !!document.querySelector('#challenge-running, #cf-challenge-running');
        const titleText = document.title || '';
        const bodyText = (document.body && document.body.innerText) ? document.body.innerText.slice(0, 500) : '';
        return {
            hasTurnstileInput,
            hasTurnstileWidget,
            hasChallengeRunning,
            titleHasJustAMoment: titleText.includes('Just a moment'),
            bodyHasJustAMoment: bodyText.includes('Just a moment')
                || bodyText.includes('Checking your browser')
                || bodyText.includes('Performing security verification'),
        };
    }).catch(() => ({
        hasTurnstileInput: false,
        hasTurnstileWidget: false,
        hasChallengeRunning: false,
        titleHasJustAMoment: false,
        bodyHasJustAMoment: false,
    }));

    const urlChallenge = urlIndicatesCfChallenge(url);

    const realChallenge = urlChallenge
        || domSignals.titleHasJustAMoment
        || domSignals.bodyHasJustAMoment
        || domSignals.hasChallengeRunning
        || title.includes('Just a moment')
        || title.includes('Performing security verification');

    const turnstileSignals = domSignals.hasTurnstileInput || domSignals.hasTurnstileWidget;

    let challengeType = null;
    if (turnstileSignals || url.includes('__cf_chl')) {
        challengeType = 'turnstile';
    } else if (realChallenge) {
        challengeType = 'js_challenge';
    }

    const requireClearance = isCfClearanceRequired(antiBot);
    let blocked;
    if (requireClearance) {
        blocked = !hasCfClearance && (realChallenge || turnstileSignals);
    } else {
        blocked = realChallenge || (turnstileSignals && urlChallenge);
    }

    return {
        blocked,
        challengeType,
        hasCfClearance,
        url,
        title,
    };
}

/**
 * 检测 Turnstile 是否已通过
 * @param {import('puppeteer').Page} page
 * @returns {Promise<boolean>}
 */
async function isTurnstileSolved(page) {
    const cookies = await page.cookies().catch(() => []);
    if (cookies.some((c) => c.name === 'cf_clearance')) {
        return true;
    }

    const tokenLen = await page.evaluate(() => {
        const input = document.querySelector('[name="cf-turnstile-response"]');
        return input && input.value ? input.value.length : 0;
    }).catch(() => 0);

    return tokenLen > 20;
}

module.exports = {
    detectCloudflare,
    isTurnstileSolved,
    urlIndicatesCfChallenge,
    isCfClearanceRequired,
    sanitizePageUrlForCfSolver,
};
