import { Env } from '../config/env.js';
import { SignedRequest } from '../security/SignedRequest.js';
const getHeader = (headers, name) => {
    if (typeof headers.get === 'function') {
        const value = headers.get(name);
        return value ?? undefined;
    }
    return headers[name];
};
const hasSigningHeaders = (headers) => Boolean((getHeader(headers, 'x-zt-key-id') ?? '') ||
    (getHeader(headers, 'x-zt-timestamp') ?? '') ||
    (getHeader(headers, 'x-zt-nonce') ?? '') ||
    (getHeader(headers, 'x-zt-body-sha256') ?? '') ||
    getHeader(headers, 'x-zt-signature'));
const normalizeKeyId = (keyId) => {
    const trimmed = keyId.trim();
    if (trimmed !== '')
        return trimmed.toLowerCase();
    const appNameRaw = Env.get('APP_NAME', 'zintrust');
    const normalized = (appNameRaw.trim() === '' ? 'zintrust' : appNameRaw)
        .toLowerCase()
        .replaceAll(/\s+/g, '_');
    return normalized;
};
const normalizeSecret = (secret) => {
    const trimmed = secret.trim();
    if (trimmed !== '')
        return trimmed;
    return Env.get('APP_KEY', '');
};
const normalizeSigningIdentity = (input) => ({
    ...input,
    keyId: normalizeKeyId(input.keyId),
    secret: normalizeSecret(input.secret),
});
const normalizeConfig = (signing) => normalizeSigningIdentity(signing);
export const normalizeSigningConfig = (signing) => normalizeConfig(signing);
export const normalizeSigningCredentials = (input) => normalizeSigningIdentity(input);
const shouldVerify = (signing, headers) => {
    const normalized = normalizeConfig(signing);
    if (normalized.require)
        return true;
    if (normalized.keyId.trim() !== '' &&
        normalized.secret.trim() !== '' &&
        hasSigningHeaders(headers)) {
        return true;
    }
    return false;
};
const mapVerifyResult = (result) => {
    if (result.ok)
        return { ok: true };
    if (result.code === 'MISSING_HEADER' || result.code === 'INVALID_TIMESTAMP') {
        return { ok: false, status: 401, code: result.code, message: result.message };
    }
    if (result.code === 'EXPIRED') {
        return { ok: false, status: 401, code: result.code, message: result.message };
    }
    if (result.code === 'UNKNOWN_KEY') {
        return { ok: false, status: 403, code: result.code, message: result.message };
    }
    if (result.code === 'REPLAYED') {
        return { ok: false, status: 409, code: result.code, message: result.message };
    }
    return { ok: false, status: 403, code: result.code, message: result.message };
};
const verifyAndMap = async (params) => mapVerifyResult(await SignedRequest.verify(params));
const verify = async (params) => {
    const signing = normalizeConfig(params.signing);
    if (signing.require && (signing.keyId.trim() === '' || signing.secret.trim() === '')) {
        return {
            ok: false,
            status: 500,
            code: 'SIGNING_REQUIRED',
            message: 'Proxy signing is required but not configured',
        };
    }
    return verifyAndMap({
        method: params.method,
        url: params.url,
        body: params.body,
        headers: params.headers,
        // eslint-disable-next-line @typescript-eslint/require-await
        getSecretForKeyId: async (keyId) => keyId.trim().toLowerCase() === signing.keyId ? signing.secret : undefined,
        windowMs: signing.windowMs,
    });
};
const verifyWithKeyProvider = async (params) => {
    return verifyAndMap({
        method: params.method,
        url: params.url,
        body: params.body,
        headers: params.headers,
        windowMs: params.windowMs,
        getSecretForKeyId: params.getSecretForKeyId,
        verifyNonce: params.verifyNonce,
    });
};
export const SigningService = Object.freeze({
    normalizeConfig,
    shouldVerify,
    verify,
    verifyWithKeyProvider,
});
