/**
 * BrowserFactory：standard / real 双轨启动 + 温池 + 独立并发限流
 */
const {
    DEFAULT_UA,
    MAX_CONCURRENT_BROWSERS,
    MAX_CONCURRENT_BROWSERS_REAL,
    QUEUE_TIMEOUT_MS,
    NAVIGATION_TIMEOUT_MS,
    PAGE_DEFAULT_TIMEOUT_MS,
} = require('./constants');
const { BrowserConcurrencyLimiter } = require('./concurrency');
const { launchStandardBrowser } = require('./launch-standard');
const { launchRealBrowser, isRealBrowserAvailable } = require('./launch-real-browser');
const { browserPool } = require('./browser-pool');

const standardLimiter = new BrowserConcurrencyLimiter(MAX_CONCURRENT_BROWSERS);
const realLimiter = new BrowserConcurrencyLimiter(MAX_CONCURRENT_BROWSERS_REAL);

function normalizeAntiBot(antiBot) {
    if (!antiBot || !antiBot.enabled) {
        return { enabled: false, profile: 'standard' };
    }
    return {
        enabled: true,
        profile: antiBot.profile === 'real' ? 'real' : 'standard',
        turnstile: antiBot.turnstile !== false,
        solverFallback: antiBot.solverFallback !== false,
        cfClearanceRequired: antiBot.cfClearanceRequired !== false,
        sessionKey: antiBot.sessionKey || '',
        challengeTimeoutMs: antiBot.challengeTimeoutMs || 60000,
        postCfReadyUrlContains: antiBot.postCfReadyUrlContains || '',
        postCfReadySelector: antiBot.postCfReadySelector || '',
        postCfReadyTimeoutMs: antiBot.postCfReadyTimeoutMs || 0,
        postCfSettleMs: antiBot.postCfSettleMs || 0,
        postCfSpaWaitMs: antiBot.postCfSpaWaitMs || 0,
        businessHostHint: antiBot.businessHostHint || '',
        landingUrlHint: antiBot.landingUrlHint || '',
    };
}

function getLimiter(profile) {
    return profile === 'real' ? realLimiter : standardLimiter;
}

/**
 * 冷启动 Browser（供温池 launcher 使用）
 * @param {{ profile?: 'standard'|'real', extraArgs?: string[], sessionKey?: string }} options
 */
async function createBrowserSession(options = {}) {
    const profile = options.profile === 'real' ? 'real' : 'standard';
    const extraArgs = options.extraArgs || [];
    const sessionKey = options.sessionKey || '';

    if (profile === 'real') {
        const { browser, page } = await launchRealBrowser(extraArgs, { sessionKey, profile: 'real' });
        return {
            browser,
            page,
            profile: 'real',
            cleanup: async (destroy = false) => {
                if (!destroy) {
                    return;
                }
                try {
                    await browser.close();
                } catch (_) { /* ignore */ }
            },
        };
    }

    const browser = await launchStandardBrowser(extraArgs, { sessionKey, profile: 'standard' });
    return {
        browser,
        page: null,
        profile: 'standard',
        cleanup: async (destroy = false) => {
            if (!destroy) {
                return;
            }
            try {
                await browser.close();
            } catch (_) { /* ignore */ }
        },
    };
}

/**
 * 从温池或冷启动获取 Browser
 * @param {{ profile?: 'standard'|'real', extraArgs?: string[], sessionKey?: string }} options
 */
async function acquireBrowserSession(options = {}) {
    const profile = options.profile === 'real' ? 'real' : 'standard';
    const sessionKey = options.sessionKey || '';
    const extraArgs = options.extraArgs || [];

    return browserPool.acquire(sessionKey, profile, async () => createBrowserSession({
        profile,
        extraArgs,
        sessionKey,
    }));
}

async function runWithProfileLimit(taskName, profile, fn) {
    const limiter = getLimiter(profile);
    try {
        return await limiter.run(taskName, fn);
    } catch (err) {
        if (err.message === 'QUEUE_TIMEOUT') err.code = 'QUEUE_TIMEOUT';
        throw err;
    }
}

async function createManagedPage(browser, existingPage, options = {}) {
    const page = existingPage || await browser.newPage();
    page.setDefaultNavigationTimeout(NAVIGATION_TIMEOUT_MS);
    page.setDefaultTimeout(PAGE_DEFAULT_TIMEOUT_MS);

    if (!options.skipUserAgent) {
        const userAgent = options.userAgent || DEFAULT_UA;
        await page.setUserAgent(userAgent);
    }

    if (options.viewport) await page.setViewport(options.viewport);
    if (options.cookies && options.cookies.length > 0) {
        await page.setCookie(...options.cookies);
    }

    page.on('error', (err) => console.error('[Page Error]', err.message));
    page.on('pageerror', (err) => console.error('[Page JS Error]', err.message));

    return page;
}

function getFactoryStats() {
    return {
        standard: standardLimiter.getStats(),
        real: realLimiter.getStats(),
        realBrowserReady: isRealBrowserAvailable(),
        pool: browserPool.getStats(),
    };
}

module.exports = {
    normalizeAntiBot,
    getLimiter,
    createBrowserSession,
    acquireBrowserSession,
    runWithProfileLimit,
    createManagedPage,
    getFactoryStats,
    standardLimiter,
    realLimiter,
    browserPool,
    QUEUE_TIMEOUT_MS,
};
