'use strict';
const request = require('superagent');
const parse = require('async-busboy');
const path = require('path')
const fs = require('fs');
const OSS = require('ali-oss');
const uuid = require('uuid');

const UploadPath = {
    project: ['.txt', '.dwg', '.doc', '.docx', '.xls', '.xlsx', ".csv", '.pdf', '.pptx', '.png', '.jpg', '.svg', '.rar', '.zip', '.jpeg', '.mp4'],
    report: ['.doc', '.docx', '.xls', '.xlsx', ".csv", '.pdf'],
    data: ['.txt', '.xls', '.xlsx', ".csv"],
    image: ['.png', '.jpg', '.svg'],
    three: ['.js'],
    video: ['.mp4']
};
const ext = {
    project: ['.txt', '.dwg', '.doc', '.docx', '.xls', '.xlsx', ".csv", '.pdf', '.pptx', '.png', '.jpg', '.gif', '.svg', '.rar', '.zip', '.jpeg', '.mp4'],
    report: [".doc", ".docx", ".xls", ".xlsx", ".pdf"],
    data: [".txt", ".xls", ".xlsx"],
    image: [".png", ".jpg", ".svg"],
    three: [".js"],
    video: [".mp4"],
    bpmn: [".bpmn", ".bpmn20.xml", ".zip", ".bar"],
    app: [".apk"]
}

module.exports = {
    entry: function (app, router, opts) {
        let download_ = async function (ctx, next) {
            const { fetchUrl } = opts.qiniu;
            const { fetchUrl: aliFetchUrl, bucket, region } = opts.aliOss
            if (ctx.path && ctx.path.includes(fetchUrl)) {
                try {
                    const { filename } = ctx.request.query;
                    const fkey = decodeURI(ctx.path.slice(fetchUrl.length + 1)).replace(/\.json$/, '.js');
                    if (ctx.path) {
                        const extNames = ctx.path.split('.');
                        app.fs.logger.log('info', 'extNames', extNames);
                        if (extNames.length > 0) {
                            let fileType = extNames[extNames.length - 1].toLowerCase();
                            if (fileType === 'pdf') {
                                ctx.type = 'application/pdf';
                                app.fs.logger.log('info', 'application/pdf', fileType);
                            }
                        }
                    }
                    const publicDownloadUrl = await app.fs.attachment.download(fkey);
                    ctx.status = 200;
                    if (filename) ctx.attachment(filename);
                    ctx.body = request.get(publicDownloadUrl);
                } catch (err) {
                    ctx.fs.logger.error(err);
                    ctx.status = 404;
                    ctx.body = { error: 'file not found.' };
                }
            } else if (ctx.path && ctx.path.includes(aliFetchUrl)) {
                const { filename } = ctx.request.query;
                const fkey = decodeURI(ctx.path.slice(aliFetchUrl.length + 1)).replace(/\.json$/, '.js');
                if (ctx.path) {
                    const extNames = ctx.path.split('.');
                    app.fs.logger.log('info', 'extNames', extNames);
                    if (extNames.length > 0) {
                        let fileType = extNames[extNames.length - 1].toLowerCase();
                        if (fileType === 'pdf') {
                            ctx.type = 'application/pdf';
                            app.fs.logger.log('info', 'application/pdf', fileType);
                        }
                    }
                }
                const publicDownloadUrl = `http://${bucket}.${region}.aliyuncs.com/${encodeURIComponent(fkey)}`
                ctx.status = 200;
                ctx.body = request.get(publicDownloadUrl);
            } else {
                await next();
            }
        };

        let upload = async function (ctx, next) {
            try {
                const { files } = await parse(ctx.req);
                const file = files[0];
                const extname = path.extname(file.filename).toLowerCase();
                const fileType = ctx.query.type || "image";
                const fileFolder = ctx.query.fileFolder || 'common';
                if (ext[fileType].indexOf(extname) < 0) {
                    ctx.status = 400;
                    ctx.body = JSON.stringify({ name: 'UploadFailed', message: '文件格式无效' });
                    return;
                }
                const date = new Date().toLocaleDateString();
                const time = new Date().getTime();
                let fileName = time + '_' + file.filename;
                let saveFile = path.join(__dirname, '../../', `/client/assets/files/${fileFolder}`, fileName);
                const pathUrl = `./client/assets/files/${fileFolder}`;

                const res1 = fs.existsSync(`./client/assets/files/${fileFolder}`);
                !res1 && fs.mkdirSync(`./client/assets/files/${fileFolder}`);
                const res = fs.existsSync(pathUrl);
                !res && fs.mkdirSync(pathUrl);
                let stream = fs.createWriteStream(saveFile);
                fs.createReadStream(file.path).pipe(stream);
                stream.on('error', function (err) {
                    app.fs.logger.log('error', '[Upload Heatmap]', err);
                });
                ctx.status = 200;
                ctx.body = { filename: path.join(`/assets/files/${fileFolder}`, fileName), name: 'UploadSuccess', message: '上传成功' };
            } catch (err) {
                ctx.status = 500;
                ctx.fs.logger.error(err);
                ctx.body = { err: 'upload error.' };
            }
        }

        let remove = async function (ctx, next) {
            try {
                const fkeys = ctx.request.body;
                let removeUrl = path.join(__dirname, '../../', './client', fkeys.url);
                const res = fs.existsSync(removeUrl);
                if (!res) {
                    ctx.status = 400;
                    ctx.body = JSON.stringify({ name: 'DeleteFailed', message: '文件地址不存在' });
                    return;
                }
                fs.unlink(removeUrl, function (error) {
                    if (error) {
                        console.log(error);
                    }
                })
                ctx.status = 200;
                ctx.body = { name: 'DeleteSuccess.', message: '删除成功' };
            } catch (err) {
                ctx.status = 500;
                ctx.fs.logger.error(err);
                ctx.body = { err: 'upload cleanup error.' };
            }
        }
        let upload_ = async function (ctx, next) {
            let fkey = null;
            try {
                const { p } = ctx.params;
                const { files } = await parse(ctx.req);
                const file = files[0];
                const extname = path.extname(file.filename).toLowerCase();
                if (!UploadPath[p]) {
                    ctx.status = 400;
                    ctx.body = JSON.stringify({ error: '附件存放的文件夹名称无效' });
                    return;
                } else if (UploadPath[p].indexOf(extname) < 0) {
                    ctx.status = 400;
                    ctx.body = JSON.stringify({ error: '文件格式无效' });
                    return;
                } else {
                    const fileInfo = await ctx.app.fs.attachment.upload(file, { uploadPath: p });
                    fkey = fileInfo.key;
                    ctx.body = { uploaded: fkey };
                }
            } catch (err) {
                ctx.status = 500;
                ctx.fs.logger.error(err);
                ctx.body = { err: 'upload error.' };
            }
        }

        const uploadAliOSS = async (ctx,) => {
            // 这个是上传到阿里
            try {
                const { aliOss } = opts
                const { p = 'default' } = ctx.params;
                const { files } = await parse(ctx.req);
                const file = files[0];
                const filename = file.filename || path.basename(file);

                const client = new OSS({
                    // yourRegion填写Bucket所在地域.以华东1(杭州)为例,Region填写为oss-cn-hangzhou.
                    region: aliOss.region,
                    // 阿里云账号AccessKey拥有所有API的访问权限,风险很高.强烈建议您创建并使用RAM用户进行API访问或日常运维,请登录RAM控制台创建RAM用户.
                    accessKeyId: aliOss.accessKey,
                    accessKeySecret: aliOss.secretKey,
                    // 填写Bucket名称,例如examplebucket.
                    bucket: aliOss.bucket,
                });

                let uploadPath = path.posix.join(p, uuid.v4(), filename);
                let result = await client.putStream(
                    uploadPath,
                    file,
                    // { contentLength: size }
                );

                ctx.status = 200;
                ctx.body = {
                    key: result.name,
                    uploaded: result.name,
                    url: result.url,
                };
            } catch (error) {
                ctx.status = 400;
                ctx.fs.logger.error(error);
                ctx.body = { err: 'upload error.' };
            }
        }

        const downloadFromAli = async (ctx) => {
            try {
                const { aliOss } = opts
                const { path, filename } = ctx.query
                const client = new OSS({
                    // yourRegion填写Bucket所在地域.以华东1(杭州)为例,Region填写为oss-cn-hangzhou.
                    region: aliOss.region,
                    // 阿里云账号AccessKey拥有所有API的访问权限,风险很高.强烈建议您创建并使用RAM用户进行API访问或日常运维,请登录RAM控制台创建RAM用户.
                    accessKeyId: aliOss.accessKey,
                    accessKeySecret: aliOss.secretKey,
                    // 填写Bucket名称,例如examplebucket.
                    bucket: aliOss.bucket,
                });

                const filename_ = filename || path.split('/').pop()

                const result = await client.get(path);
                ctx.status = 200;
                ctx.set('Content-Type', 'application/x-xls');
                ctx.set('Content-disposition', 'attachment; filename=' + filename_);
                ctx.body = result.content;
            } catch (error) {
                ctx.status = 400;
                ctx.fs.logger.error(error);
                ctx.body = { err: 'download error.' };
            }
        }

        router.use(download_);
        router.post('/_upload/new', upload);
        router.delete('/_upload/cleanup', remove);
        router.post('/_upload/attachments/ali/:p', uploadAliOSS);
        router.get('/_download/attachments/ali', downloadFromAli);
        router.post('/_upload/attachments/:p', upload_);
    }
};