import '../assert_dev_env.js';
/**
 * Parse the `name=value` head of a `Set-Cookie` value. Returns `null`
 * for malformed inputs (missing `=`, empty name). Drops every attribute
 * after the first `;` — the jar is name-keyed and the lifetime
 * attributes (`Expires`, `Max-Age`, `Path`, `Domain`, `SameSite`)
 * don't affect cross-process test plumbing.
 */
const parse_set_cookie = (value) => {
    const head = value.split(';', 1)[0].trim();
    const eq = head.indexOf('=');
    if (eq <= 0)
        return null;
    const name = head.slice(0, eq).trim();
    if (!name)
        return null;
    return { name, cookie: head };
};
/**
 * Build a cookie-threading transport pinned to `options.base_url`. The
 * returned function carries a private `Map<name, cookie-head>` jar that
 * updates on every response's `Set-Cookie` and re-sends on every
 * subsequent request.
 *
 * Request rewriting:
 *
 * - Absolute URLs (`http://other.example/...`) pass through verbatim —
 *   handy for cross-origin negative tests that target a deliberately
 *   different host.
 * - Relative URLs are resolved against `base_url`.
 * - `Origin` is set to `options.origin ?? base_url` unless the caller
 *   already provided one.
 * - `Cookie` is set from the jar unless the caller already provided one.
 */
export const create_fetch_transport = (options) => {
    const { base_url, initial_cookies, origin } = options;
    const jar = new Map();
    if (initial_cookies) {
        for (const raw of initial_cookies) {
            const parsed = parse_set_cookie(raw);
            if (parsed)
                jar.set(parsed.name, parsed.cookie);
        }
    }
    const default_origin = origin === null ? null : (origin ?? base_url);
    const cookies = () => Array.from(jar.values());
    const transport = (async (url, init) => {
        const target = /^https?:\/\//i.test(url) ? url : `${base_url}${url}`;
        const headers = new Headers(init.headers);
        if (default_origin !== null && !headers.has('Origin')) {
            headers.set('Origin', default_origin);
        }
        if (!headers.has('Cookie') && jar.size > 0) {
            headers.set('Cookie', Array.from(jar.values()).join('; '));
        }
        const response = await fetch(target, { ...init, headers });
        // `Headers.getSetCookie()` returns each `Set-Cookie` value as a
        // separate string — the only way to read multiple cookies set in
        // one response (Headers.get() collapses to a single comma-joined
        // string). Node 19.7+ ships it; vitest's runtime supports it.
        const set_cookies = response.headers.getSetCookie();
        for (const raw of set_cookies) {
            const parsed = parse_set_cookie(raw);
            if (parsed)
                jar.set(parsed.name, parsed.cookie);
        }
        return response;
    });
    // Attach the cookies() accessor onto the callable. Using a property
    // definition keeps it non-enumerable-ish and avoids polluting `.bind`
    // / `.call` reflection on the function.
    Object.defineProperty(transport, 'cookies', { value: cookies, enumerable: false });
    return transport;
};
