import notificationConfig from '../../config/notification.js';
import { ErrorFactory } from '../../exceptions/ZintrustError.js';
import { NotificationConfig } from './config.js';
import { ConsoleDriver } from './drivers/Console.js';
import { SlackDriver } from './drivers/Slack.js';
import { TwilioDriver } from './drivers/Twilio.js';
import { NotificationChannelRegistry } from './NotificationChannelRegistry.js';
import { NotificationRegistry } from './Registry.js';
const assertValidRecipientAndMessage = (recipient, message) => {
    if (typeof recipient !== 'string' || recipient.trim() === '') {
        throw ErrorFactory.createValidationError('Recipient required');
    }
    if (typeof message !== 'string' || message.trim() === '') {
        throw ErrorFactory.createValidationError('Message required');
    }
};
const resolveChannelConfig = (channelName) => {
    const selected = String(channelName ?? '').trim();
    const hasSelection = selected.length > 0;
    return hasSelection && NotificationChannelRegistry.has(selected)
        ? NotificationChannelRegistry.get(selected)
        : notificationConfig.getDriverConfig(selected);
};
const sendTermii = async (cfg, recipient, message, options) => {
    const apiKey = String(cfg.apiKey ?? '');
    if (apiKey.trim() === '') {
        throw ErrorFactory.createConfigError('TERMII_API_KEY is not configured');
    }
    const url = String(cfg.endpoint ?? '').trim();
    if (url === '') {
        throw ErrorFactory.createConfigError('TERMII_ENDPOINT is not configured');
    }
    const payload = {
        to: recipient,
        from: cfg.sender,
        sms: message,
        api_key: apiKey,
        ...options,
    };
    const res = await globalThis.fetch(url, {
        method: 'POST',
        headers: { 'Content-Type': 'application/json' },
        body: JSON.stringify(payload),
    });
    if (!res.ok) {
        const txt = await res.text().catch(() => '');
        throw ErrorFactory.createTryCatchError(`Termii request failed (${res.status})`, {
            status: res.status,
            body: txt,
        });
    }
    return res.json().catch(() => ({}));
};
export const NotificationService = Object.freeze({
    async send(recipient, message, options = {}) {
        assertValidRecipientAndMessage(recipient, message);
        const driverName = NotificationConfig.getDriver();
        const driver = NotificationRegistry.get(driverName);
        return driver.send(recipient, message, options);
    },
    async sendVia(channelName, recipient, message, options = {}) {
        assertValidRecipientAndMessage(recipient, message);
        const cfg = resolveChannelConfig(channelName);
        switch (cfg.driver) {
            case 'console':
                return ConsoleDriver.send(recipient, message, options);
            case 'slack': {
                const slackCfg = cfg;
                const payload = { text: message, ...options };
                return SlackDriver.send({ webhookUrl: slackCfg.webhookUrl }, payload);
            }
            case 'twilio': {
                const twilioCfg = cfg;
                return TwilioDriver.send({
                    accountSid: twilioCfg.accountSid,
                    authToken: twilioCfg.authToken,
                    from: twilioCfg.fromNumber,
                }, { to: recipient, body: message });
            }
            case 'termii': {
                return sendTermii(cfg, recipient, message, options);
            }
            default:
                throw ErrorFactory.createConfigError(`Notification: unsupported driver: ${String(cfg?.driver)}`);
        }
    },
    listDrivers() {
        return NotificationRegistry.list();
    },
});
export default NotificationService;
