const axios = require('axios');
const fs = require('fs/promises');
const {createWriteStream} = require('fs');
const path = require('path');

module.exports = Self => {
    Self.remoteMethod('download', {
        description: 'Processes the image download queue',
        accessType: 'WRITE',
        http: {
            path: `/download`,
            verb: 'POST',
        },
        accessScopes: ['DEFAULT', 'read:multimedia']
    });

    Self.download = async() => {
        const models = Self.app.models;
        const tempContainer = await models.TempContainer.container(
            'salix-image'
        );
        const tempPath = path.join(
            tempContainer.client.root,
            tempContainer.name
        );
        const maxAttempts = 3;
        const collectionName = 'catalog';

        let tempFilePath;
        let queueRow;
        try {
            queueRow = await Self.findOne(
                {
                    fields: ['id', 'itemFk', 'url', 'attempts'],
                    where: {
                        url: {neq: null},
                        attempts: {
                            lt: maxAttempts,
                        },
                    },
                    order: 'priority, attempts, updated',
                }
            );

            if (!queueRow) return;

            const fileName = `${queueRow.itemFk}.png`;
            tempFilePath = path.join(tempPath, fileName);

            // Download remote image
            const response = await axios.get(queueRow.url, {
                responseType: 'stream',
            });

            const writeStream = createWriteStream(tempFilePath);
            await new Promise((resolve, reject) => {
                writeStream.on('open', () => response.data.pipe(writeStream));
                writeStream.on('finish', () => resolve());
                writeStream.on('error', error => reject(error));
            });

            await models.Image.resize({
                collectionName: collectionName,
                srcFile: tempFilePath,
                fileName: fileName,
                entityId: queueRow.itemFk
            });

            try {
                await fs.unlink(tempFilePath);
            } catch (error) { }

            await queueRow.destroy();

            // Restart queue
            Self.download();
        } catch (error) {
            if (queueRow.attempts < maxAttempts) {
                await queueRow.updateAttributes({
                    error: error,
                    attempts: queueRow.attempts + 1,
                    updated: Date.vnNew(),
                });
            }

            try {
                await fs.unlink(tempFilePath);
            } catch (error) { }

            Self.download();
        }
    };
};