const fs = require('fs');
const ora = require('ora');
const chalk = require('chalk');
const webpack = require('webpack');
const path = require('path');
const qrcode = require('qrcode-terminal');
const zipDir = require('zip-directory');
const superagent = require('superagent');

const renderConfig = require('./webpack.render');
const serviceConfig = require('./webpack.service');
const getIpAddress = require('./getIpAddress');

const { _root, _src, _config } = require('./getBlConfig.js');
const ROOT = path.join(process.cwd(), _root);
const SRC = path.join(ROOT, _src);
const DIST = path.join(ROOT, _config, 'dist');
const express = require('express');


if (!fs.existsSync(path.join(ROOT, 'zip'))) {
    fs.mkdirSync(path.join(ROOT, 'zip'));
}
if (!process.env.TEST_BUILDER && process.argv.indexOf('no-serve') === -1) {
    const app = express();
    app.get('/', (req, res) => res.send('Small App Static Server'));
    app.use(express.static(path.join(ROOT, 'zip')));
    app.listen(3000, () => {
        // console.log('真机调试服务正在运行，可以用手机扫码调试构建出来的安装包啦')
    });
}

const spinner = ora('building for pages...');
spinner.start();
webpack(renderConfig(ROOT), (err, stats) => {
            spinner.stop();
            if (err) {
                throw err;
            }

            process.stdout.write(stats.toString({
                colors: true,
                modules: false,
                children: false,
                chunks: false,
                chunkModules: false
            }) + '\n\n');

            console.log(chalk.cyan('  Build pages complete.\n'));

            webpack(serviceConfig(ROOT, SRC), (err, stats) => {
                        if (err) {
                            throw err;
                        }
                        process.stdout.write(stats.toString({
                            colors: true,
                            modules: false,
                            children: false,
                            chunks: false,
                            chunkModules: false
                        }) + '\n\n');

                        fs.unlink(path.join(SRC, 'service.js'), () => {});

                        const zipName = new Date().toJSON().replace(/[-:.TZ]/g, '') + '.zip';
                        if (!fs.existsSync(path.join(ROOT, 'zip'))) {
                            fs.mkdirSync(path.join(ROOT, 'zip'));
                        }
                        const zipPath = path.join(ROOT, 'zip', zipName);
                        const latestZipPath = path.join(ROOT, 'zip', 'latest.zip');
                        const packageInfo = require(path.join(ROOT, _config, 'package.json'));

                        fs.writeFileSync(path.join(DIST, `bilibili_ver_${packageInfo.version}`), '', 'utf8');

                        zipDir(DIST, zipPath, () => {
                                    fs.unlink(latestZipPath, () => {
                                                fs.copyFile(zipPath, latestZipPath, async() => {
                                                            const ip = getIpAddress();
                                                            const sapprc = JSON.parse(fs.readFileSync(path.join(ROOT, _config, '.sapprc'), 'utf8'));
                                                            let storageId = '';
                                                            let debugURL = `https://miniapp.bilibili.com/applet/debug/${sapprc.appId}_${sapprc.vAppId}?url=${encodeURIComponent(`http://${ip}:3000/${zipName}`)}`;
                    let midStr = '';

                    process.argv.some(arg => {
                        if (arg.indexOf('mid') === 0) {
                            midStr = arg;
                            return true;
                        }
                    })

                    if (midStr) {
                        // mid=xxx
                        let mid = midStr.slice(4);
                        
                        try {
                            let uploadUrl = '';
    
                            let upZipResponse = await superagent
                                .post('http://mall-mng.bilibili.co/mall-mng/picture/image')
                                .attach('file', latestZipPath, zipName);
                            if (upZipResponse.status === 200 && upZipResponse.body.code === 0 && upZipResponse.body.data) {
                                uploadUrl = 'http:' + upZipResponse.body.data;
                            } else {
                                console.log('本地构建失败，请重试');
                                process.exit();
                                return;
                            }
    
                            let upResponse = await superagent
                                .post('http://miniapp.bilibili.com/api/storage/dev_storage/upload')
                                .send({ appId: sapprc.appId, url: uploadUrl, mid, isValidUrl: 0 })
                                .set('Accept', 'application/json');
                            if (upResponse.status === 200 && upResponse.body.code === 0) {
                                storageId = upResponse.body.data;
                                debugURL = `https://miniapp.bilibili.com/applet/dev-${sapprc.appId}?_biliStorageId=${storageId}`;
                            } else {
                                console.log('本地构建失败：', upResponse.body.message);
                                process.exit();
                                return;
                            }
                        } catch (error) {
                            console.log('本地构建失败，请重试');
                            process.exit();
                            return;
                        }
                    }
                    
                    console.log(chalk.cyan('  Build service complete.\n'));
                    if (process.env.TEST_BUILDER || process.argv.indexOf('no-serve') !== -1) {
                        console.log(11211)
                        return;
                    }

                    let devtoolPort;
                    // 调试工具静态端口一般从10022开始
                    // 发现window版本扫描接口较慢，这里就不做过多的扫描了
                    for (let i = 10022; i < 10028; i++) {
                        try {
                            const response = await superagent.post(`http://localhost:${i}/devtool-scan`).send({});
                            console.warn(i)
                            if (response.status === 200 && response.text === 'small-app-devtool-application listened...') {
                                devtoolPort = i;
                                break;
                            }
                        } catch (error) {
                            console.error(error);
                        }
                    }
                    console.log('=========', devtoolPort)
                    if (devtoolPort) {
                        await superagent.post(`http://localhost:${devtoolPort}/devtool-debug`).send({ debugURL });
                        console.log(chalk.cyan('检测到调试工具正在运行，可以使用调试工具进行调试啦'));
                    } else {
                        qrcode.generate(debugURL);
                        console.log(debugURL);
                        console.log(chalk.cyan('真机调试服务正在运行，可以用手机扫码调试构建出来的安装包啦'));
                    }
                    console.log(chalk.cyan('若要重新构建需退出（ctrl+c），再执行一次 npm run build'));
                });
            });
        });
    });
});