const moment = require('moment');

const { generateService, parseParamsToFindOptions } = require('../../helpers/service.helper');
const userDeviceService = require('./user_device.service');
const notificationDetailService = require('./notification_detail.service');
const pushHelper = require('../../helpers/push.helper');
const models = require('../../core/models');

const saveNotification = (notification) => extraMethods.saveNotification(notification);

const getUserDevices = async (userId) => {
    const result = await userDeviceService.fetchAll({ params: { userId: userId } }, {});    
    return result.rows;
};

const disableUserDevice = (token) => userDeviceService.update({
    params: {
        token: token,
    }
}, { valid: 0, invalidated: moment() }, {});


const disableInvalidUserDevices = async (devices) => {
    console.log(devices);
    const okDevices = [];
    devices.forEach(async (device) => {
        if (!userDeviceService.isValidPushToken(device.token)) {
            await disableUserDevice(device.token);
        } else {
            okDevices.push(device);
        }
    });

    return okDevices;
};

const buildPushMessages = (notification, devices) => {
    let messages = [];
    
    devices.forEach(async function (device) {
        messages.push(pushHelper.createPushMessage({
            ...notification,
            userId: device.userId,
            to: device.token,
        }));
    });

    return messages;    
};

const disableUserDevicesWithErrorStatus = (messages, tickets) => {
    tickets.forEach(async function (ticket, index) {
        if ((ticket.status === 'error') && (ticket.details.error === 'DeviceNotRegistered')) {
            disableUserDevice(messages[index].to)
        }
    });
}

let saveResponseStatusPromise = (messages, tickets) => notificationDetailService.saveNotificationDetails(messages, tickets);







const extraMethods = {

    /*createNotification: (data) => {
        return {
            date: data.date,
            title: data.title,
            body: data.body,
            ttl: data.ttl,
            priority: data.priority,
            recipients: data.recipients,
            data: data.data,
            userId: data.userId,
        }
    },*/

    saveNotification: ({ date, title, body, ttl, priority, recipients, data, userId }) => {
        return models.Notification.create({
            date: moment(date),
            title: title,
            body: body,
            userId: userId,
            ttl: ttl ? ttl : undefined,
            priority: priority ? priority : 'default',
            recipients: recipients,
            data: data,
        });
    },


    /*sendNotificationToUsers: (notification, userIds) => {

        console.log('sendNotificationToUsers -----------------------------------------------');
        console.log(notification, userIds);

        let getUserDevicesList = [];

        saveNotificationPromise(notification)
            .then(function (notificationRecord) {
                notification = notificationRecord.toJSON();
                userIds.forEach(function (userId) {
                    getUserDevicesList.push(getUserDevicesPromise(userId));
                });

                return Promise.all(getUserDevicesList)
            }).then(function (userDeviceList) {
                let result = [];
                userDeviceList.forEach(function (elements) {
                    elements.forEach(function (item) {
                        result.push(item)
                    })
                });
                return new Promise(function (resolve) { resolve(result); });
            })
            .then(disableInvalidUserDevicesPromise)
            .then(buildMessagesPromise)
            .then(sendNotificationsPromise)
            .then(function ({ messages, tickets }) {
                let _saveStatus = saveResponseStatusPromise(messages, tickets);
                let _disableDevices = disableUserDevicesWithErrorStatus(messages, tickets);

                return Promise.all([_saveStatus, _disableDevices]);
            })
            .then(function (details) {
                console.log(details);
                return details;
            });
    },*/


    sendNotificationToUsers: async (notification, userIds) => {
     
        console.log('sendNotificationToUsers -----------------------------------------------');
        console.log(notification);

        const savedNotification = (await saveNotification(notification)).toJSON();

       const userDevicesList = await Promise.all(userIds.map((userId) => getUserDevices(userId)));


        const allDevices = userDevicesList.flat();            
        const validDevices = await disableInvalidUserDevices(allDevices);

        const pushMessages = buildPushMessages(savedNotification, validDevices);

      
        const { messages, tickets } = await pushHelper.sendPushMessage(pushMessages);
        saveResponseStatusPromise(messages, tickets);
        disableUserDevicesWithErrorStatus(messages, tickets);
        
        return;
    },


    
    sendNotificationToDevices: async (notification, devicesIds) => {
     
        console.log('sendNotificationToDevices -----------------------------------------------');
        console.log(notification);

        const savedNotification = (await saveNotification(notification)).toJSON();

        const validDevices = await disableInvalidUserDevices(devicesIds);
        const pushMessages = buildPushMessages(savedNotification, validDevices);

    
        const { messages, tickets } = await pushHelper.sendPushMessage(pushMessages);
        saveResponseStatusPromise(messages, tickets);
        disableUserDevicesWithErrorStatus(messages, tickets);
        
        return;
    },






    getNotificationsWithoutReceipt: async () => {

    },

    updateNotificationsWithReceipts: async (receiptIds) => {

        //let receiptIdChunks = expo.chunkPushNotificationReceiptIds(receiptIds);
        //let xxx = await _getPushNotificationsResultAsync(receiptIdChunks);

    }
};

module.exports = generateService(models.Notification, extraMethods);



