/**
 * 将发往字面量 IPv4 的 https 请求改写为 http。
 * 用于云控面板 HTTP 入口对浏览器返回 307 升级 HTTPS、但 IP 上 443 不可达的场景。
 */
'use strict';

function rewriteHttpsToHttpForLiteralIp(url) {
    try {
        const parsed = new URL(url);
        if (parsed.protocol !== 'https:') {
            return url;
        }
        if (!/^\d{1,3}(\.\d{1,3}){3}$/.test(parsed.hostname)) {
            return url;
        }
        parsed.protocol = 'http:';
        return parsed.toString();
    } catch (_) {
        return url;
    }
}

async function attachHttpIpRewriteInterceptor(page, contextLabel = 'page', options = {}) {
    const shareToken = typeof options.shareToken === 'string' ? options.shareToken : '';
    const blockHeavyResources = options.blockHeavyResources !== false;
    await page.setRequestInterception(true);
    page.on('request', (req) => {
        if (req.isInterceptResolutionHandled()) {
            return;
        }
        if (blockHeavyResources) {
            const resourceType = req.resourceType();
            if (['image', 'media', 'font'].includes(resourceType)) {
                req.abort();
                return;
            }
        }
        const originalUrl = req.url();
        const rewrittenUrl = rewriteHttpsToHttpForLiteralIp(originalUrl);
        if (rewrittenUrl !== originalUrl) {
            const continueOptions = { url: rewrittenUrl };
            if (shareToken) {
                const headers = { ...req.headers() };
                const existingCookie = headers.cookie || headers.Cookie || '';
                if (!existingCookie.includes('share_token=')) {
                    headers.cookie = existingCookie
                        ? `${existingCookie}; share_token=${shareToken}`
                        : `share_token=${shareToken}`;
                }
                continueOptions.headers = headers;
            }
            req.continue(continueOptions);
            return;
        }
        req.continue();
    });
}

module.exports = {
    rewriteHttpsToHttpForLiteralIp,
    attachHttpIpRewriteInterceptor,
};
