import "@js-temporal/polyfill";
import "urlpattern-polyfill";
import { d as name, f as version, l as UrlError, o as getUserAgent, u as validatePublicUrl } from "./docloader-C7Hk8BRD.js";
import { getLogger } from "@logtape/logtape";
import { SpanKind, SpanStatusCode, trace } from "@opentelemetry/api";
//#region src/webfinger/lookup.ts
const logger = getLogger([
	"fedify",
	"webfinger",
	"lookup"
]);
const DEFAULT_MAX_REDIRECTION = 5;
/**
* Looks up a WebFinger resource.
* @param resource The resource URL to look up.
* @param options Extra options for looking up the resource.
* @returns The resource descriptor, or `null` if not found.
* @since 0.2.0
*/
async function lookupWebFinger(resource, options = {}) {
	return await (options.tracerProvider ?? trace.getTracerProvider()).getTracer(name, version).startActiveSpan("webfinger.lookup", {
		kind: SpanKind.CLIENT,
		attributes: {
			"webfinger.resource": resource.toString(),
			"webfinger.resource.scheme": typeof resource === "string" ? resource.replace(/:.*$/, "") : resource.protocol.replace(/:$/, "")
		}
	}, async (span) => {
		try {
			const result = await lookupWebFingerInternal(resource, options);
			span.setStatus({ code: result === null ? SpanStatusCode.ERROR : SpanStatusCode.OK });
			return result;
		} catch (error) {
			span.setStatus({
				code: SpanStatusCode.ERROR,
				message: String(error)
			});
			throw error;
		} finally {
			span.end();
		}
	});
}
async function lookupWebFingerInternal(resource, options = {}) {
	if (typeof resource === "string") resource = new URL(resource);
	let protocol = "https:";
	let server;
	if (resource.protocol === "acct:") {
		const atPos = resource.pathname.lastIndexOf("@");
		if (atPos < 0) return null;
		server = resource.pathname.substring(atPos + 1);
		if (server === "") return null;
	} else {
		protocol = resource.protocol;
		server = resource.host;
	}
	let url = new URL(`${protocol}//${server}/.well-known/webfinger`);
	url.searchParams.set("resource", resource.href);
	let redirected = 0;
	while (true) {
		logger.debug("Fetching WebFinger resource descriptor from {url}...", { url: url.href });
		let response;
		if (options.allowPrivateAddress !== true) try {
			await validatePublicUrl(url.href);
		} catch (e) {
			if (e instanceof UrlError) {
				logger.error("Invalid URL for WebFinger resource descriptor: {error}", { error: e });
				return null;
			}
			throw e;
		}
		try {
			response = await fetch(url, {
				headers: {
					Accept: "application/jrd+json",
					"User-Agent": typeof options.userAgent === "string" ? options.userAgent : getUserAgent(options.userAgent)
				},
				redirect: "manual",
				signal: options.signal
			});
		} catch (error) {
			logger.debug("Failed to fetch WebFinger resource descriptor: {error}", {
				url: url.href,
				error
			});
			return null;
		}
		if (response.status >= 300 && response.status < 400 && response.headers.has("Location")) {
			redirected++;
			const maxRedirection = options.maxRedirection ?? DEFAULT_MAX_REDIRECTION;
			if (redirected >= maxRedirection) {
				logger.error("Too many redirections ({redirections}) while fetching WebFinger resource descriptor.", { redirections: redirected });
				return null;
			}
			const redirectedUrl = new URL(response.headers.get("Location"), response.url == null || response.url === "" ? url : response.url);
			if (redirectedUrl.protocol !== url.protocol) {
				logger.error("Redirected to a different protocol ({protocol} to {redirectedProtocol}) while fetching WebFinger resource descriptor.", {
					protocol: url.protocol,
					redirectedProtocol: redirectedUrl.protocol
				});
				return null;
			}
			url = redirectedUrl;
			continue;
		}
		if (!response.ok) {
			logger.debug("Failed to fetch WebFinger resource descriptor: {status} {statusText}.", {
				url: url.href,
				status: response.status,
				statusText: response.statusText
			});
			return null;
		}
		try {
			return await response.json();
		} catch (e) {
			if (e instanceof SyntaxError) {
				logger.debug("Failed to parse WebFinger resource descriptor as JSON: {error}", { error: e });
				return null;
			}
			throw e;
		}
	}
}
//#endregion
export { lookupWebFinger as t };
