const path = require('path');
const os = require('os');
const multer = require('multer');
const fs = require('fs-extra');
const errors = require('@tryghost/errors');
const config = require('../../../../shared/config');
const {i18n} = require('../../../lib/common');
const logging = require('../../../../shared/logging');

const upload = {
    enabledClear: config.get('uploadClear') || true,
    multer: multer({dest: os.tmpdir()})
};

const deleteSingleFile = file => fs.unlink(file.path).catch(err => logging.error(err));

const single = name => (req, res, next) => {
    const singleUpload = upload.multer.single(name);
    singleUpload(req, res, (err) => {
        if (err) {
            return next(err);
        }
        if (upload.enabledClear) {
            const deleteFiles = () => {
                res.removeListener('finish', deleteFiles);
                res.removeListener('close', deleteFiles);
                if (!req.disableUploadClear) {
                    if (req.files) {
                        return req.files.forEach(deleteSingleFile);
                    }

                    if (req.file) {
                        return deleteSingleFile(req.file);
                    }
                }
            };
            if (!req.disableUploadClear) {
                res.on('finish', deleteFiles);
                res.on('close', deleteFiles);
            }
        }
        next();
    });
};

const checkFileExists = (fileData) => {
    return !!(fileData.mimetype && fileData.path);
};

const checkFileIsValid = (fileData, types, extensions) => {
    const type = fileData.mimetype;

    if (types.includes(type) && extensions.includes(fileData.ext)) {
        return true;
    }

    return false;
};

const validation = function (options) {
    const type = options.type;

    // if we finish the data/importer logic, we forward the request to the specified importer
    return function uploadValidation(req, res, next) {
        const extensions = (config.get('uploads')[type] && config.get('uploads')[type].extensions) || [];
        const contentTypes = (config.get('uploads')[type] && config.get('uploads')[type].contentTypes) || [];

        req.file = req.file || {};
        req.file.name = req.file.originalname;
        req.file.type = req.file.mimetype;

        // Check if a file was provided
        if (!checkFileExists(req.file)) {
            return next(new errors.ValidationError({
                message: i18n.t(`errors.api.${type}.missingFile`)
            }));
        }

        req.file.ext = path.extname(req.file.name).toLowerCase();

        // Check if the file is valid
        if (!checkFileIsValid(req.file, contentTypes, extensions)) {
            return next(new errors.UnsupportedMediaTypeError({
                message: i18n.t(`errors.api.${type}.invalidFile`, {extensions: extensions})
            }));
        }

        next();
    };
};

module.exports = {
    single,
    validation
};

// Exports for testing only
module.exports._test = {
    checkFileExists,
    checkFileIsValid
};
