function isHttpUrl(url) {
    return url.protocol === "http:" || url.protocol === "https:";
}

function makeScopePattern(url) {
    const normalized = new URL(url.href);
    normalized.hash = "";
    normalized.search = "";
    return normalized.href.endsWith("/")
        ? `${normalized.href}*`
        : `${normalized.href}/*`;
}

function getManifestAllowedUrls(manifest, manifestURL, pageURL) {
    if (!manifest || typeof manifest !== "object") return [];

    let manifestBase;
    let page;
    try {
        manifestBase = new URL(manifestURL);
        page = new URL(pageURL);
    } catch (error) {
        return [];
    }

    if (!isHttpUrl(manifestBase) || !isHttpUrl(page)) return [];

    const allowedUrls = new Set();
    const addSameOriginUrl = (value, asScope = false) => {
        if (typeof value !== "string" || !value) return;
        try {
            const resolved = new URL(value, manifestBase);
            if (!isHttpUrl(resolved) || resolved.origin !== page.origin) return;
            allowedUrls.add(asScope ? makeScopePattern(resolved) : resolved.href);
        } catch (error) {
            // Ignore malformed manifest members.
        }
    };

    addSameOriginUrl(manifest.scope, true);
    addSameOriginUrl(manifest.start_url);

    if (Array.isArray(manifest.scope_extensions)) {
        for (const extension of manifest.scope_extensions) {
            const originValue = typeof extension === "string"
                ? extension
                : extension?.origin;
            if (typeof originValue !== "string" || !originValue) continue;

            try {
                const extensionUrl = new URL(originValue);
                if (!isHttpUrl(extensionUrl)
                    || extensionUrl.hostname.includes("*")
                    || extensionUrl.username
                    || extensionUrl.password) continue;
                allowedUrls.add(`${extensionUrl.origin}/*`);
            } catch (error) {
                // Ignore malformed or wildcard origins; an origin must be exact.
            }
        }
    }

    return [...allowedUrls];
}

module.exports = { getManifestAllowedUrls };
