import * as crypto from "node:crypto";
import { URL } from "node:url";
export function createSignedPost(args) {
    const u = new URL(args.url);
    const digestHeader = `SHA-256=${crypto.createHash("sha256").update(args.body).digest("base64")}`;
    const request = {
        url: u.href,
        method: "POST",
        headers: objectAssignWithLcKey({
            Date: new Date().toUTCString(),
            Host: u.hostname,
            "Content-Type": "application/activity+json",
            Digest: digestHeader
        }, args.additionalHeaders)
    };
    const result = signToRequest(request, args.key, [
        "(request-target)",
        "date",
        "host",
        "digest"
    ]);
    return {
        request,
        signingString: result.signingString,
        signature: result.signature,
        signatureHeader: result.signatureHeader
    };
}
export function createSignedGet(args) {
    const u = new URL(args.url);
    const request = {
        url: u.href,
        method: "GET",
        headers: objectAssignWithLcKey({
            Accept: "application/activity+json, application/ld+json; profile=\"https://www.w3.org/ns/activitystreams\"",
            Date: new Date().toUTCString(),
            Host: new URL(args.url).hostname
        }, args.additionalHeaders)
    };
    const result = signToRequest(request, args.key, [
        "(request-target)",
        "date",
        "host",
        "accept"
    ]);
    return {
        request,
        signingString: result.signingString,
        signature: result.signature,
        signatureHeader: result.signatureHeader
    };
}
function signToRequest(request, key, includeHeaders) {
    const signingString = genSigningString(request, includeHeaders);
    const signature = crypto.sign("sha256", Buffer.from(signingString), key.privateKeyPem).toString("base64");
    const signatureHeader = `keyId="${key.keyId}",algorithm="rsa-sha256",headers="${includeHeaders.join(" ")}",signature="${signature}"`;
    request.headers = objectAssignWithLcKey(request.headers, {
        Signature: signatureHeader
    });
    return {
        request,
        signingString,
        signature,
        signatureHeader
    };
}
function genSigningString(request, includeHeaders) {
    request.headers = lcObjectKey(request.headers);
    const results = [];
    for (const key of includeHeaders.map((x)=>x.toLowerCase())){
        if (key === "(request-target)") {
            results.push(`(request-target): ${request.method.toLowerCase()} ${new URL(request.url).pathname}`);
        } else {
            results.push(`${key}: ${request.headers[key]}`);
        }
    }
    return results.join("\n");
}
function lcObjectKey(src) {
    const dst = {};
    for (const key of Object.keys(src).filter((x)=>x !== "__proto__" && typeof src[x] === "string"))dst[key.toLowerCase()] = src[key];
    return dst;
}
function objectAssignWithLcKey(a, b) {
    return Object.assign(lcObjectKey(a), lcObjectKey(b));
}
