const fs = require('fs');
const _ = require('lodash');
const express = require('express');
const formidable = require('formidable');
const bunker = require('./bunker');
const sendHandledRequest = require('../lib/sendHandledRequest');

const MAX_FILE_SIZE = 104857600; // 100 MB

module.exports = () => {
    let router = express.Router(); // eslint-disable-line new-cap

    router.use('/directory/', (req, res) => {
        let method = req.method.toLowerCase();
        let url = `${req.config.api.directory}/v11${req.path}`;

        if (req.is('multipart')) {
            let form = new formidable.IncomingForm();
            let files = [];

            form.maxFieldsSize = MAX_FILE_SIZE;

            let request = new Promise((resolve, reject) => {
                let data = {};

                form.on('file', (key, file) => {
                    data[key] = {
                        value: fs.createReadStream(file.path),
                        options: {
                            filename: `temp_${Math.random().toString(36).slice(2)}`,
                            contentType: file.type,
                        },
                    };

                    files.push(file.path);
                });

                form.on('field', (key, value) => {
                    data[key] = value;
                });

                form.on('end', () => {
                    resolve(data);
                });

                form.on('error', err => {
                    reject({ statusCode: 500, body: err });
                });
            })
                .then(data => {
                    return sendHandledRequest({
                        method,
                        url,
                        formData: data,
                        body: null,
                        source: req,
                        label: 'multipart_directory_proxy',
                    });
                })
                .then(data => {
                    files.forEach(file => fs.existsSync(file) && fs.unlinkSync(file));

                    res.json(data);
                })
                .catch(({ statusCode, body = {} }) => {
                    res.status(statusCode).json(body);
                });

            form.parse(req);

            return request;
        }

        return sendHandledRequest({
            method,
            url,
            source: req,
            label: 'directory_proxy',
            encoding: req.get('x-encoding') === 'binary' ? null : undefined,
        }, true)
            .then(({ body, response }) => {
                res.type(response.headers['content-type']).send(body);
            })
            .catch(({ statusCode, body = {}, headers = {} }) => {
                res.status(statusCode).type(headers['content-type'] || 'text').send(body);
            });
    });

    router.use('/setter/', (req, res) => {
        return sendHandledRequest({
            method: req.method.toLowerCase(),
            url: `${req.config.api.setter}${req.path}`,
            headers: {
                'X-Ya-Service-Ticket': _.get(req.context, 'tvm_tickets.setter'),
            },
            source: req,
            label: 'setter_proxy',
            noTrailingSlash: true,
        })
            .then(data => {
                res.json(data);
            })
            .catch(({ statusCode, body = {} }) => {
                res.status(statusCode).json(body);
            });
    });

    router.use('/fouras/', (req, res) => {
        return sendHandledRequest({
            method: req.method.toLowerCase(),
            url: `${req.config.api.fouras}${req.path}`,
            headers: {
                'X-Ya-Service-Ticket': _.get(req.context, 'tvm_tickets.fouras'),
            },
            source: req,
            label: 'fouras_proxy',
            noTrailingSlash: true,
        })
            .then(data => {
                res.json(data);
            })
            .catch(({ statusCode, body = {} }) => {
                res.status(statusCode).json(body);
            });
    });

    router.use('/settings/', (req, res) => {
        return sendHandledRequest({
            method: req.method.toLowerCase(),
            url: `${req.config.api.settings}${req.path}`,
            headers: {
                ...req.context.headers,
                Authorization: `Token ${req.config.tokens.settings}`,
                'Content-Type': 'application/json',
            },
            noTrailingSlash: true,
            source: req,
            label: 'settings_proxy',
        })
            .then(data => {
                res.json(data);
            })
            .catch(({ statusCode, body = {} }) => {
                res.status(statusCode).json({ broken: true, ...body });
            });
    });

    router.use('/sender/', (req, res) => {
        return sendHandledRequest({
            method: req.method.toLowerCase(),
            url: `${req.config.api.sender}${req.path}`,
            options: {
                formData: req.body,
                auth: {
                    user: req.config.tokens.sender,
                    pass: '',
                },
            },
            noTrailingSlash: true,
            source: req,
            label: 'sender_proxy',
        })
            .then(data => {
                res.json(data);
            })
            .catch(({ statusCode, body = {} }) => {
                res.status(statusCode).json(body);
            });
    });

    router.use('/gendarme/', (req, res) => {
        return sendHandledRequest({
            method: req.method.toLowerCase(),
            url: `${req.config.api.gendarme}${req.path}`,
            headers: {
                'X-Ya-Service-Ticket': req.context.tvm_tickets.gendarme,
            },
            noTrailingSlash: true,
            source: req,
            label: 'gendarme_proxy',
        })
            .then(data => {
                res.json(data);
            })
            .catch(({ statusCode, body = {} }) => {
                res.status(statusCode).json(body);
            });
    });

    router.use('/dns/', (req, res) => {
        return sendHandledRequest({
            method: req.method.toLowerCase(),
            url: `${req.config.api.dns}${req.path}`,
            headers: {
                ...req.context.headers,
                'X-Ya-Service-Ticket': req.context.tvm_tickets.dns,
            },
            source: req,
            label: 'dns_proxy',
        })
            .then(data => {
                res.json(data);
            })
            .catch(({ statusCode, body = {} }) => {
                res.status(statusCode).json(body);
            });
    });

    router.route('/bunker').all(bunker);

    return router;
};
