/**
 * 付费 Captcha API 兜底：CapSolver / 2Captcha 统一 Turnstile 求解接口
 */
const {
    CAPTCHA_PROVIDER,
    CAPTCHA_API_KEY,
    CAPTCHA_MAX_WAIT_MS,
} = require('./constants');

/**
 * @param {string} url
 * @param {Record<string, string>} [headers]
 * @returns {Promise<any>}
 */
async function httpJsonPost(url, body, headers = {}) {
    const res = await fetch(url, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json', ...headers },
        body: JSON.stringify(body),
    });
    const text = await res.text();
    try {
        return JSON.parse(text);
    } catch (_) {
        throw new Error(`Captcha API 返回非 JSON: ${text.slice(0, 200)}`);
    }
}

/**
 * @param {string} url
 * @returns {Promise<any>}
 */
async function httpJsonGet(url) {
    const res = await fetch(url);
    const text = await res.text();
    try {
        return JSON.parse(text);
    } catch (_) {
        throw new Error(`Captcha API 返回非 JSON: ${text.slice(0, 200)}`);
    }
}

/**
 * CapSolver Turnstile 求解
 * @param {{ pageUrl: string, sitekey: string, apiKey: string }} params
 * @returns {Promise<string>}
 */
async function solveViaCapSolver({ pageUrl, sitekey, apiKey }) {
    const create = await httpJsonPost('https://api.capsolver.com/createTask', {
        clientKey: apiKey,
        task: {
            type: 'AntiTurnstileTaskProxyLess',
            websiteURL: pageUrl,
            websiteKey: sitekey,
        },
    });

    if (create.errorId !== 0 || !create.taskId) {
        throw new Error(`CapSolver createTask 失败: ${create.errorDescription || create.errorCode || 'unknown'}`);
    }

    const deadline = Date.now() + CAPTCHA_MAX_WAIT_MS;
    while (Date.now() < deadline) {
        await new Promise((r) => setTimeout(r, 3000));
        const result = await httpJsonPost('https://api.capsolver.com/getTaskResult', {
            clientKey: apiKey,
            taskId: create.taskId,
        });

        if (result.status === 'ready' && result.solution && result.solution.token) {
            return result.solution.token;
        }
        if (result.errorId !== 0) {
            throw new Error(`CapSolver getTaskResult 失败: ${result.errorDescription || result.errorCode}`);
        }
    }
    throw new Error('CapSolver 求解超时');
}

/**
 * 2Captcha Turnstile 求解
 * @param {{ pageUrl: string, sitekey: string, apiKey: string }} params
 * @returns {Promise<string>}
 */
async function solveVia2Captcha({ pageUrl, sitekey, apiKey }) {
    const params = new URLSearchParams({
        key: apiKey,
        method: 'turnstile',
        sitekey,
        pageurl: pageUrl,
        json: '1',
    });

    const create = await httpJsonGet(`https://2captcha.com/in.php?${params.toString()}`);
    if (create.status !== 1 || !create.request) {
        throw new Error(`2Captcha in.php 失败: ${create.request || create.error_text || 'unknown'}`);
    }

    const taskId = create.request;
    const deadline = Date.now() + CAPTCHA_MAX_WAIT_MS;
    while (Date.now() < deadline) {
        await new Promise((r) => setTimeout(r, 5000));
        const result = await httpJsonGet(
            `https://2captcha.com/res.php?key=${encodeURIComponent(apiKey)}&action=get&id=${encodeURIComponent(taskId)}&json=1`
        );
        if (result.status === 1 && result.request) {
            return result.request;
        }
        if (result.request && result.request !== 'CAPCHA_NOT_READY') {
            throw new Error(`2Captcha res.php 失败: ${result.request}`);
        }
    }
    throw new Error('2Captcha 求解超时');
}

/**
 * 统一 Turnstile 求解入口
 * @param {{ pageUrl: string, sitekey: string, provider?: string, apiKey?: string }} params
 * @returns {Promise<{ token: string, provider: string }>}
 */
async function solveTurnstile({ pageUrl, sitekey, provider, apiKey }) {
    const resolvedProvider = (provider || CAPTCHA_PROVIDER).toLowerCase();
    const resolvedKey = apiKey || CAPTCHA_API_KEY;

    if (!sitekey) {
        throw new Error('无法提取 Turnstile sitekey');
    }
    if (!resolvedKey) {
        throw new Error('未配置 CAPTCHA_API_KEY，无法使用付费 Captcha 兜底');
    }

    let token;
    if (resolvedProvider === '2captcha') {
        token = await solveVia2Captcha({ pageUrl, sitekey, apiKey: resolvedKey });
    } else {
        token = await solveViaCapSolver({ pageUrl, sitekey, apiKey: resolvedKey });
    }

    return { token, provider: resolvedProvider };
}

/**
 * Captcha API 是否已配置
 * @returns {boolean}
 */
function isCaptchaConfigured() {
    return CAPTCHA_API_KEY.length > 0;
}

module.exports = {
    solveTurnstile,
    isCaptchaConfigured,
};
