"use strict";
var __importDefault = (this && this.__importDefault) || function (mod) {
    return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.OneSignalPushGateway = void 0;
const axios_1 = __importDefault(require("axios"));
const toArgbHex = (color) => {
    const hex = color.replace('#', '');
    if (hex.length === 6) {
        return `FF${hex.toUpperCase()}`;
    }
    return hex.toUpperCase();
};
const isPushNotification = (message) => {
    const candidate = message;
    return (typeof candidate === 'object' &&
        candidate !== null &&
        typeof candidate.recipient === 'object' &&
        candidate.recipient !== null &&
        typeof candidate.amount === 'object' &&
        candidate.amount !== null);
};
/**
 * OneSignal REST API implementation of the notification gateway.
 *
 * Translates internal device IDs into OneSignal player IDs (push tokens)
 * stored on the device record and sends push notifications via the
 * OneSignal `/notifications` endpoint.
 */
class OneSignalPushGateway {
    appId;
    restApiKey;
    deviceRepository;
    logger;
    constructor(appId, restApiKey, deviceRepository, logger) {
        this.appId = appId;
        this.restApiKey = restApiKey;
        this.deviceRepository = deviceRepository;
        this.logger = logger;
    }
    async sendToDevice(deviceId, message) {
        const notification = message;
        const device = await this.deviceRepository.findById(deviceId);
        if (!device?.pushToken) {
            this.logger.debug('[OneSignal] Skipping push: device has no push token', {
                deviceId,
            });
            return;
        }
        const payload = isPushNotification(message)
            ? this.buildStyledPayload(device.pushToken, message)
            : this.buildFallbackPayload(device.pushToken, notification);
        this.logger.debug('[OneSignal] Sending push notification', {
            deviceId,
            pushToken: device.pushToken,
            transactionId: notification.transaction.id,
        });
        try {
            await axios_1.default.post('https://api.onesignal.com/notifications', payload, {
                headers: {
                    Authorization: `Basic ${this.restApiKey}`,
                    'Content-Type': 'application/json',
                },
            });
            this.logger.debug('[OneSignal] Push notification sent', {
                deviceId,
                transactionId: notification.transaction.id,
            });
        }
        catch (error) {
            this.logger.error('[OneSignal] Failed to send push notification', {
                deviceId,
                pushToken: device.pushToken,
                transactionId: notification.transaction.id,
                error,
            });
        }
    }
    isDeviceConnected(_deviceId) {
        // Push notifications are always reachable from the server perspective.
        // The presence of a push token is checked in sendToDevice.
        return true;
    }
    buildStyledPayload(pushToken, notification) {
        const { recipient, amount } = notification;
        const counterparty = recipient.counterpartyAddress;
        let title;
        let body;
        if (recipient.isSender) {
            title = `💸 Sent: ${amount.formatted} ${amount.symbol}`;
            body = counterparty ? `To ${this.shortenAddress(counterparty)}` : 'To external address';
        }
        else if (recipient.isReceiver) {
            title = `💰 Received: ${amount.formatted} ${amount.symbol}`;
            body = counterparty ? `From ${this.shortenAddress(counterparty)}` : 'From external address';
        }
        else {
            title = 'Transaction received';
            body = `Transaction ${this.shortenAddress(notification.transaction.hash)} is confirmed`;
        }
        return {
            app_id: this.appId,
            include_player_ids: [pushToken],
            headings: { en: title },
            contents: { en: body },
            data: {
                type: notification.type,
                transactionId: notification.transaction.id,
                status: notification.transaction.status,
            },
            // Priority 10 = max; needed for Android heads-up notifications.
            priority: 10,
            android_visibility: 1,
            ios_badgeType: 'Increase',
            ios_badgeCount: 1,
            small_icon: 'notification_icon',
            accent_color: toArgbHex('#5092f8'),
        };
    }
    buildFallbackPayload(pushToken, notification) {
        const transaction = notification.transaction;
        return {
            app_id: this.appId,
            include_player_ids: [pushToken],
            headings: { en: 'Transaction received' },
            contents: {
                en: `Transaction ${this.shortenAddress(transaction.hash)} is ${transaction.status}`,
            },
            data: {
                type: notification.type,
                transactionId: transaction.id,
                status: transaction.status,
            },
            priority: 10,
            android_visibility: 1,
            ios_badgeType: 'Increase',
            ios_badgeCount: 1,
            small_icon: 'notification_icon',
            accent_color: toArgbHex('#5092f8'),
        };
    }
    shortenAddress(address) {
        if (address.length <= 12) {
            return address;
        }
        return `${address.slice(0, 6)}...${address.slice(-4)}`;
    }
}
exports.OneSignalPushGateway = OneSignalPushGateway;
//# sourceMappingURL=onesignal-push-gateway.js.map