/* eslint-disable no-await-in-loop */
import ErrorEvent from "../libs/error";
import { uploadFromUrl } from "../libs/aws";
import { getAlbumDetails } from "../helpers";

import JobsModel from "../models/jobs";
import AlbumsModel from "../models/albums";

class Jobs {
    /**
     * Méthode permettant de télécharger toute les images d'un album
     * @param {ObjectId} itemId
     */
    static async importAlbumAssets(itemId) {
        const album = await AlbumsModel.findById(itemId);

        if (!album) {
            throw new ErrorEvent(
                404,
                "Item non trouvé",
                `L'album avant l'id ${itemId} n'existe plus dans la collection`
            );
        }

        const item = await getAlbumDetails(album.discogsId);

        if (!item) {
            throw new ErrorEvent(
                404,
                "Erreur de communication",
                "Erreur lors de la récupération des informations sur Discogs"
            );
        }

        if (item.thumb) {
            album.thumb = await uploadFromUrl(item.thumb);
            album.thumbType = "local";
        }
        const { images } = item;
        if (images && images.length > 0) {
            for (let i = 0; i < images.length; i += 1) {
                images[i].uri150 = await uploadFromUrl(images[i].uri150);
                images[i].uri = await uploadFromUrl(images[i].uri);
            }
        }

        album.images = images;

        await album.save();

        return true;
    }

    /**
     * Point d'entrée
     * @param {String} state
     *
     * @return {Object}
     */
    async run(state = "NEW") {
        const job = await JobsModel.findOne({
            state,
            tries: {
                $lte: 5,
            },
        });

        if (!job) {
            return { message: "All jobs done" };
        }

        job.state = "IN-PROGRESS";

        await job.save();

        try {
            switch (job.model) {
                case "Albums":
                    await Jobs.importAlbumAssets(job.id);
                    break;
                default:
                    throw new ErrorEvent(
                        500,
                        "Job inconnu",
                        `Le job avec l'id ${job._id} n'est pas un job valide`
                    );
            }

            job.state = "SUCCESS";

            await job.save();

            return this.run(state);
        } catch (err) {
            job.state = "ERROR";
            job.lastTry = new Date();
            job.lastErrorMessage = err.message;
            job.tries += 1;

            await job.save();

            throw err;
        }
    }

    /**
     * Méthode permettant de créer tous les jobs
     *
     * @return {Object}
     */
    static async populate() {
        const albums = await AlbumsModel.find();

        for (let i = 0; i < albums.length; i += 1) {
            const jobData = {
                model: "Albums",
                id: albums[i]._id,
            };

            const job = new JobsModel(jobData);
            await job.save();
        }

        return { message: `${albums.length} jobs ajouté à la file d'attente` };
    }
}

export default Jobs;