import { readEnvString } from '../../../common/ExternalServiceUtils.js';
import { AwsSigV4 } from '../../../common/index.js';
import { ErrorFactory } from '../../../exceptions/ZintrustError.js';
const sha256Hex = (data) => AwsSigV4.sha256Hex(data);
const buildAuthorization = (params) => {
    const canonicalUri = params.path;
    const canonicalQueryString = '';
    const headers = {
        'content-type': 'application/json',
        host: params.host,
        'x-amz-date': params.amzDate,
    };
    if (params.credentials.sessionToken !== null && params.credentials.sessionToken !== undefined) {
        headers['x-amz-security-token'] = params.credentials.sessionToken;
    }
    const payloadHash = sha256Hex(params.body);
    return AwsSigV4.buildAuthorization({
        method: params.method,
        canonicalUri,
        canonicalQueryString,
        headers,
        payloadHash,
        region: params.region,
        service: 'ses',
        amzDate: params.amzDate,
        dateStamp: params.dateStamp,
        credentials: params.credentials,
    });
};
const ensureRegion = (config) => {
    const region = typeof config.region === 'string' ? config.region.trim() : '';
    if (region === '')
        throw ErrorFactory.createConfigError('SES: missing region in config');
    return region;
};
const ensureCredentials = () => {
    const accessKeyId = readEnvString('AWS_ACCESS_KEY_ID');
    const secretAccessKey = readEnvString('AWS_SECRET_ACCESS_KEY');
    const sessionToken = readEnvString('AWS_SESSION_TOKEN') ?? undefined;
    if (accessKeyId.length === 0 || secretAccessKey.length === 0) {
        throw ErrorFactory.createConfigError('SES: missing AWS credentials (set AWS_ACCESS_KEY_ID and AWS_SECRET_ACCESS_KEY)');
    }
    return { accessKeyId, secretAccessKey, sessionToken };
};
const buildBody = (message) => {
    const toAddresses = Array.isArray(message.to) ? message.to : [message.to];
    const body = {
        FromEmailAddress: message.from.email,
        Destination: { ToAddresses: toAddresses },
        Content: {
            Simple: {
                Subject: { Data: message.subject },
                Body: {
                    Text: { Data: message.text },
                    ...(typeof message.html === 'string' && message.html !== ''
                        ? { Html: { Data: message.html } }
                        : {}),
                },
            },
        },
    };
    return JSON.stringify(body);
};
const buildHeaders = (amzDate, authorization, sessionToken) => {
    const headers = {
        'content-type': 'application/json',
        'x-amz-date': amzDate,
        Authorization: authorization,
    };
    if (typeof sessionToken === 'string' && sessionToken !== '')
        headers['x-amz-security-token'] = sessionToken;
    return headers;
};
export const SesDriver = Object.freeze({
    async send(config, message) {
        const region = ensureRegion(config);
        const { accessKeyId, secretAccessKey, sessionToken } = ensureCredentials();
        const bodyJson = buildBody(message);
        const host = `email.${region}.amazonaws.com`;
        const path = '/v2/email/outbound-emails';
        const url = `https://${host}${path}`;
        const now = new Date();
        const { amzDate, dateStamp } = AwsSigV4.toAmzDate(now);
        const { authorization } = buildAuthorization({
            method: 'POST',
            host: host,
            region,
            amzDate,
            dateStamp,
            credentials: { accessKeyId, secretAccessKey, sessionToken },
            body: bodyJson,
            path,
        });
        const headers = buildHeaders(amzDate, authorization, sessionToken);
        const res = await fetch(url, {
            method: 'POST',
            headers,
            body: bodyJson,
        });
        if (res.ok) {
            try {
                const json = (await res.json());
                const messageId = typeof json?.['MessageId'] === 'string' ? json['MessageId'] : undefined;
                return { ok: true, provider: 'ses', messageId };
            }
            catch {
                return { ok: true, provider: 'ses' };
            }
        }
        const text = await res.text();
        throw ErrorFactory.createConnectionError(`SES send failed (${res.status})`, {
            status: res.status,
            body: text,
        });
    },
});
export default SesDriver;
