/// JavaScript that patches `window.fetch` and `XMLHttpRequest` to record all
/// network requests into `window.__tailfin_net`.
pub(super) const INJECT_INTERCEPTOR_JS: &str = r#"
(() => {
    if (window.__tailfin_net) return 'already_installed';
    window.__tailfin_net = [];

    // --- Patch fetch ---
    const _origFetch = window.fetch;
    window.fetch = async function(...args) {
        const resp = await _origFetch.apply(this, args);
        try {
            const url = typeof args[0] === 'string' ? args[0] : (args[0]?.url || '');
            const method = (args[1]?.method || 'GET').toUpperCase();
            const ct = resp.headers.get('content-type') || '';
            const reqHeaders = {};
            if (args[1]?.headers) {
                const h = args[1].headers;
                if (typeof h.forEach === 'function') {
                    h.forEach((v, k) => { reqHeaders[k] = v; });
                } else if (typeof h === 'object') {
                    Object.keys(h).forEach(k => { reqHeaders[k] = h[k]; });
                }
            }
            let body = null;
            if (ct.includes('json')) {
                try {
                    const clone = resp.clone();
                    const text = await clone.text();
                    body = text.substring(0, 4000);
                } catch(e) {}
            }
            window.__tailfin_net.push({
                method: method,
                url: url,
                status: resp.status,
                contentType: ct,
                responseBody: body,
                requestHeaders: reqHeaders
            });
        } catch(e) {}
        return resp;
    };

    // --- Patch XMLHttpRequest ---
    const _origOpen = XMLHttpRequest.prototype.open;
    const _origSend = XMLHttpRequest.prototype.send;
    const _origSetHeader = XMLHttpRequest.prototype.setRequestHeader;

    XMLHttpRequest.prototype.open = function(method, url, ...rest) {
        this.__tf_method = (method || 'GET').toUpperCase();
        this.__tf_url = url;
        this.__tf_headers = {};
        return _origOpen.call(this, method, url, ...rest);
    };

    XMLHttpRequest.prototype.setRequestHeader = function(key, value) {
        if (this.__tf_headers) this.__tf_headers[key] = value;
        return _origSetHeader.call(this, key, value);
    };

    XMLHttpRequest.prototype.send = function(...args) {
        this.addEventListener('load', function() {
            try {
                const ct = this.getResponseHeader('content-type') || '';
                let body = null;
                if (ct.includes('json')) {
                    body = (this.responseText || '').substring(0, 4000);
                }
                window.__tailfin_net.push({
                    method: this.__tf_method || 'GET',
                    url: this.__tf_url || '',
                    status: this.status,
                    contentType: ct,
                    responseBody: body,
                    requestHeaders: this.__tf_headers || {}
                });
            } catch(e) {}
        });
        return _origSend.apply(this, args);
    };

    return 'installed';
})()
"#;

/// JavaScript that scrolls down the page 3 times with 1.5s delays.
pub(super) const AUTO_SCROLL_JS: &str = r#"
(async () => {
    for (let i = 0; i < 3; i++) {
        window.scrollBy(0, window.innerHeight);
        await new Promise(r => setTimeout(r, 1500));
    }
    return 'scrolled';
})()
"#;

/// JavaScript that returns page metadata.
pub(super) const READ_METADATA_JS: &str = r#"
JSON.stringify({ url: location.href, title: document.title })
"#;

/// JavaScript that discovers API endpoints from Performance API entries
/// (captures requests that happened before our interceptor was injected)
/// and re-fetches them to capture response bodies.
pub(super) const DISCOVER_APIS_FROM_PERFORMANCE_JS: &str = r#"
(async () => {
    if (!window.__tailfin_net) window.__tailfin_net = [];
    const seen = new Set(window.__tailfin_net.map(e => e.url));
    const resources = performance.getEntriesByType('resource');
    const apiResources = resources.filter(r =>
        (r.initiatorType === 'fetch' || r.initiatorType === 'xmlhttprequest') &&
        !seen.has(r.name)
    );
    for (const r of apiResources.slice(0, 10)) {
        try {
            const resp = await fetch(r.name, { credentials: 'include' });
            const ct = resp.headers.get('content-type') || '';
            let body = null;
            if (ct.includes('json')) {
                try { body = (await resp.text()).substring(0, 4000); } catch {}
            }
            window.__tailfin_net.push({
                method: 'GET', url: r.name, status: resp.status,
                contentType: ct, responseBody: body, requestHeaders: {}
            });
        } catch {}
    }
    return apiResources.length;
})()
"#;
