const dns = require('dns').promises;

function isPrivateIp(ip) {
    if (ip.includes(':')) {
        // IPv6: loopback, link-local, unique-local
        return ip === '::1' || /^fe80:/i.test(ip) || /^fc[0-9a-f]{2}:/i.test(ip) || /^fd[0-9a-f]{2}:/i.test(ip);
    }
    const parts = ip.split('.').map(Number);
    if (parts.length !== 4 || parts.some(p => Number.isNaN(p))) return true; // unparsable → sicherheitshalber blocken
    const [a, b] = parts;
    if (a === 127) return true;            // Loopback
    if (a === 10) return true;             // Private
    if (a === 172 && b >= 16 && b <= 31) return true; // Private
    if (a === 192 && b === 168) return true;          // Private
    if (a === 169 && b === 254) return true;          // Link-local
    if (a === 0) return true;              // "this network"
    return false;
}

// Wirft, falls die URL auf interne/private Adressen oder Loopback zeigt — verhindert SSRF
// über den Knowledge-Base-URL-Import (Server würde sonst beliebige interne Endpunkte abrufen).
async function assertPublicUrl(urlString) {
    const parsed = new URL(urlString);
    if (!['http:', 'https:'].includes(parsed.protocol)) {
        throw new Error('Nur HTTP/HTTPS URLs erlaubt');
    }
    const hostname = parsed.hostname;
    if (hostname === 'localhost' || hostname.endsWith('.local')) {
        throw new Error('Interne/lokale Adressen sind nicht erlaubt');
    }

    let addresses;
    try {
        addresses = await dns.lookup(hostname, { all: true });
    } catch {
        throw new Error('Hostname konnte nicht aufgelöst werden');
    }

    for (const { address } of addresses) {
        if (isPrivateIp(address)) {
            throw new Error('Interne/private Adressen sind nicht erlaubt');
        }
    }
    return parsed;
}

module.exports = { assertPublicUrl, isPrivateIp };
