var express = require('express');
var cproc = require('child_process');
var bodyParser = require('body-parser');
var request = require('request');
const mongoose = require('mongoose');
var ProConfig = require('./model/proconfig.js');
var DBconfig = require('./model/dbconfig.js');

// return
var execSync = cproc.execSync;
var options = {
    inflate: true,
    limit: '100kb',
    type: 'application/octet-stream'
};

// 同步进行接口转发
function requestPromise(option) {
    return new Promise(function (resolve, reject) {
        request(option, function (err, res, body) {
            if (err) {
                reject(err)
            } else {
                resolve(body)
            }
        })
    })
}
// mongoose.connect('mongodb://192.168.28.179:27017/qaHome');
mongoose.connect('mongodb://172.30.220.22:27017/qaHome')

var app = express();
var admin = express(); // the sub app
app.use(bodyParser.urlencoded({ extended: false }))

app.use(bodyParser.json())
var attrs = {
    configPath: "config_file",
    gitPath: "git_path",
    gitGroup: "gitPathHead",
    host: "www",
    projectType: "type",
    projectAuth: "auth",
    projectDesc: "desc",
    logName: "log_name",
    jarFilePath: "target_path",
    port: "port",
    buildCmd: "command2",
    startCmd: "command",
    stopCmd: "stop_command",
    node_version: "node_version"
}
var attrComs = Object.keys(attrs)
var attrComsArr = [];
for (let i of attrComs) {
    attrComsArr.push(attrs[i]);
}
// ------------UTILS------------
function parseStr2Json(str) {
    var a = {};
    var strs = str.split(" ");
    for (let i of strs) {
        if (i) {
            let os = i.split("|");
            a[os[0]] = {
                name: os[0],
                ip: os[1],
                http: os[2],
                https: os[3]
            }
        }
    }
    return a
}

function parseJson2Str(json) {
    var a = [];
    let keys = Object.keys(json);
    for (let k of keys) {
        a.push([
            json[k].name,
            json[k].ip,
            json[k].http,
            json[k].https
        ].join("|"))
    }
    return a.join(" ")
}

// ------------UTILS----------

// 从mongo中获取配置
function getProjectConfigPromise() {
    return new Promise(function (resolve, reject) {
        // mongoose.model("ProConfig",new mongoose.Schema({}))
        ProConfig.find({ is_active: true }).exec().then(res => {
            let _pros = JSON.parse(JSON.stringify(res));
            let re = {}, hosts = {};
            for (let pro of _pros) {
                hosts[pro["project_name"]] = pro["host_name"];
                // if (pro["project_name"] == "xjd-ui") {
                //                     hosts["xyqb-ui--xjd-ui"] = pro["host_name"];
                //                 } else
                if (pro["project_name"] == "new-paycenter-ui") {
                    hosts["paycenter-ui--new-paycenter-ui"] = pro["host_name"];
                }

                let temp = {
                    project_group: "",
                    name: pro["project_name"],
                    type: pro["type"],
                    url: pro["host_name"].replace(".xyqb.com", "").replace(".quantgroup.cn", ""),
                    www: pro["host_name"],
                    git_path: pro["git_path"],
                    log_name: pro["log_path"],
                    config_file: pro["config_path"],
                    command: "",
                    command_: "",
                    command2: "",
                    node_version: "",
                    port: `${pro["port"]}`,
                    desc: pro["des"],
                    is_active: pro["is_active"],
                    auth: pro["auth"],
                    target_path: ""
                }
                if (pro["type"] == "java") {
                    temp.node_version = pro["command1"];
                    temp.target_path = pro["jar_path"];
                    temp.command2 = pro["build_command"];
                    temp.command = pro["start_command"];
                } else if (pro["type"] == "ui") {
                    temp.command2 = pro["build_command"];
                } else if (pro["type"] == "node") {
                    temp.command = pro["start_command"]
                    temp.stop_command = pro["stop_command"]
                } else if (pro["type"] == "python") {

                }
                re[temp["name"]] = temp;
            }

            resolve({ projects: re, hosts: hosts })
        }).catch((err) => {
            reject(err)
        });
    })
}
function getProjectConfigPromiseByDb(obj) {
    return new Promise(function (resolve, reject) {
        // mongoose.model("ProConfig",new mongoose.Schema({}))
        ProConfig.find(obj).exec().then(res => {
            // let _pros = JSON.parse(JSON.stringify(res));
            resolve(res)
        }).catch((err) => {
            reject(err)
        });
    })
}
// let db_conf = db_config.db_config();
// let db_conf_keys = Object.keys(db_conf);
// 从mongo中获取DB配置
function getDBConfigPromise() {
    return new Promise(function (resolve, reject) {
        DBconfig.find({}).exec().then(res => {
            let re = {}
            let _dbs = JSON.parse(JSON.stringify(res))
            for (let db of _dbs) {
                re[db["dbname"]] = db
            }

            resolve(re)
        }).catch((err) => {
            reject(err)
        });
    })
}

// 
admin.get('/get_db_config/:name/:attr', async function (req, res) {
    let db_conf = await getDBConfigPromise();
    let db_conf_keys = Object.keys(db_conf);
    if (req.params.name == "all") {
        if (req.params.attr == "name") {
            res.send(db_conf_keys.join(" "));
        } else {
            res.send("请求参数不正确，仅支持/get_db_config/all/name")
        }
    } else if (db_conf[req.params.name]) {
        if (req.params.attr != "all") {
            if (db_conf[req.params.name][req.params.attr]) {
                res.send(db_conf[req.params.name][req.params.attr])
            } else {
                let keys = Object.keys(db_conf[req.params.name])
                res.send(req.params.name + '数据库只有这些属性：' + keys)
            }
        } else {
            let item = db_conf[req.params.name]
            // res.send(JSON.stringify(db_conf[req.params.name]))
            res.send(`${item.ip} ${item.port} ${item.username} ${item.passwd} ${item.table_list}`)
        }
    } else {
        res.send('不存在该数据库：' + req.params.name)
    }
});

admin.get('/get_db_dump_command/:name/:opt', async function (req, res) {
    let db_conf = await getDBConfigPromise();
    let db_conf_keys = Object.keys(db_conf);
    if (req.params.opt != "opt") {
        res.send(db_config.get_mysql_dump_table(req.params.name));
    } else {
        res.send(db_config.get_mysql_dump_opt(req.params.name));
    }
});

admin.get('/get_db_config/refersh', async function (req, res) {
    let db_conf = await getDBConfigPromise();
    let db_conf_keys = Object.keys(db_conf);
    res.setHeader("Content-Type", "application/json");
    res.send({ code: "OK" })
})

// 获取节点命令
admin.get('/get_node_command/:name', async function (req, res) {
    res.setHeader("Content-Type", "application/json");
    let configs = await getProjectConfigPromise();
    let projects = configs.projects
    let pro = projects[req.params.name];
    res.send({ configPath: pro.config_file, buildCmd: pro.command, gitPath: pro.git_path });
});

// 获取项目配置
admin.get('/get_project_attr/:name', async function (req, res) {
    res.setHeader("Content-Type", "application/json");
    var names = req.params.name.split("--");
    var p_name = "";
    if (names.length > 1) {
        p_name = names[0]
    } else {
        p_name = req.params.name
    }
    try {
        let configs = await getProjectConfigPromise();
        let projects = configs.projects
        let pro = projects[p_name];
        console.log(pro)
        let rs = {};
        for (let item of attrComs) {
            rs[item] = pro[attrs[item]]
        }
        res.send(rs);
    }
    catch (e) {
        console.log(e)
        res.send(e)
    }
});
// 获取项目配置具体属性
admin.get('/get_attr_from_project/:name/:attr', async function (req, res) {
    // res.setHeader("Content-Type", "text");
    var names = req.params.name.split("--");
    var p_name = "";
    if (names.length > 1) {
        p_name = names[0]
    } else {
        p_name = req.params.name
    }
		let pro = await getProjectConfigPromiseByDb({project_name:req.params.name});
		let val = pro[0][req.params.attr];
    res.send(val);
});

// 获取所有域名
admin.get('/get_hosts', async function (req, res) {
    res.setHeader("Content-Type", "application/json");
    let configs = await getProjectConfigPromise();
    res.send(configs.hosts);
});

// 根据类型获取系统名称
function getfrontendbackend(pros) {
    let temp = {
        frontend: [],
        backend: [],
        ui: [],
        node: [],
        java: [],
        python: []
    }
    let keys = Object.keys(pros)
    // console.log(keys)
    for (let key of keys) {
        let pro = pros[key]
        if (pro.type == "ui") {
            // && pro.name != "spider-center-ui" pro.name != "xyqb-ui" && 
            if (pro.name != "paycenter-ui") {
                // if (pro.name == "xjd-ui") {
                //                     temp.frontend.push("xyqb-ui--xjd-ui");
                //                     temp[pro.type].push("xyqb-ui--xjd-ui")
                //                 } else
                if (pro.name == "new-paycenter-ui") {
                    temp.frontend.push("paycenter-ui--new-paycenter-ui");
                    temp[pro.type].push("paycenter-ui--new-paycenter-ui")
                }
                // else if(pro.name == "new-spider-center-ui"){
                // 	temp.frontend.push("spider-center-ui--new-spider-center-ui");
                // 	temp[pro.type].push("spider-center-ui--new-spider-center-ui")
                // }
                else {
                    temp.frontend.push(pro.name);
                    temp[pro.type].push(pro.name)
                }
            }
        } else {
            temp.backend.push(pro.name);
            temp[pro.type].push(pro.name)
        }
    }
    return temp
}
admin.get('/get_systems_by_type', async function (req, res) {
    res.setHeader("Content-Type", "application/json");
    let configs = await getProjectConfigPromise();
    let pros = configs.projects;
    let fb = getfrontendbackend(pros);
    res.send({
        common: "db,redis,rabbitmq,zookeeper,kong,postgres,mongodb",
        frontend: fb.frontend.join(","),
        backend: fb.backend.join(",")
    });
});

// 给jenkins使用根据类型获取系统名称
admin.get('/get_systems_by_type_for_jenkins/:_type', async function (req, res) {
    let str = "";
    let configs = await getProjectConfigPromise();
    let pros = configs.projects;
    let fb = getfrontendbackend(pros);
    if (req.params._type === "frontend") {
        res.send(fb.frontend.join(" "));
    } else {
        res.send(fb.backend.join(" "));
    }
});

// 提供所有项目的所有配置
admin.get('/get_pro_configs', async function (req, res) {
    let configs = await getProjectConfigPromise();
    res.send(configs.projects);
});

// 给jenkins使用根据类型获取系统名称
admin.get('/get_systems_by_type_for_temp', async function (req, res) {
    let configs = await getProjectConfigPromise();
    let pros = configs.projects;
    let fb = getfrontendbackend(pros);
    res.send({
        ui: fb.ui.join(" "),
        java: fb.java.join(" "),
        node: fb.node.join(" "),
        python: fb.python.join(" ")
    });
});
// 给jenkins使用获取环境的namespace
admin.get('/get_namespace_by_type_for_jenkins/:_type', async function (req, res) {
    let url = "";
    if (req.params._type == "old") {
        url = "http://192.168.6.13/api/qahome/list_env"
    }
    let ns = await requestPromise({ url: url, method: "GET" });
    ns = JSON.parse(ns);
    let ns_array = [];
    for (let ist of ns.details.instances) {
        ns_array.push(ist.name)
    }
    res.send(ns_array.join("\n"));
});
// 获取这个服务的所有配置
admin.get('/get_config/:_name', async function (req, res) {
    let config = await getProjectConfigPromiseByDb({ project_name: req.params._name });
    res.send(config[0])
})


// 给jenkins使用获取服务groupname_projectname
admin.get('/get_groupname_by_type_for_jenkins/:_type', async function (req, res) {
    let configs = await getProjectConfigPromiseByDb({ is_active: true });
    let re = {
        ui: [],
        java: [],
        node: [],
        python: []
    };
    let xjdui = [["", ""], ["", ""]], payui = [["", ""], ["", ""]]
    for (let o of configs) {
        // if (o.project_name == "xyqb-ui") {
        //             xjdui[0][0] = o.git_path_group
        //             xjdui[1][0] = o.project_name
        //         } else if (o.project_name == "xjd-ui") {
        //     xjdui[0][1] = o.git_path_group
        //     xjdui[1][1] = o.project_name
        // } else
        if (o.project_name == "paycenter-ui") {
            payui[0][0] = o.git_path_group
            payui[1][0] = o.project_name
        } else if (o.project_name == "new-paycenter-ui") {
            payui[0][1] = o.git_path_group
            payui[1][1] = o.project_name
        } else {
            if (req.params._type != "lua_ui") {
                if (re[req.params._type] == undefined) {
                    re[req.params._type] = [];
                }
                re[o.type].push(`${o.git_path_group}/${o.project_name}`)
            }
        }
    }
    function getLuaUiStr(item) {
        return `${item[0][0]}--${item[0][1]}/${item[1][0]}--${item[1][1]}`
    }
    let lua_ui = [], cb = "";
    if (req.params._type == "lua_ui") {
        // lua_ui.push(getLuaUiStr(xjdui));
        lua_ui.push(getLuaUiStr(payui));
        cb = lua_ui.join("\n");
        res.send(cb);
    } else {
        res.send(re[req.params._type].join("\n"));
    }
});

// 增加一个新的nginx映射
admin.post('/add_new_proxy', function (req, res) {
    let request = req.body;
    let new_namespace = request["namespace"],
        new_ip = request["ip"],
        new_ports = request["ports"];
    var str = String(execSync(`cat ../ngrok/docker_env_name.sh`)).replace(/\n/, "");
    let data = parseStr2Json(str);
    data[new_namespace] = {
        name: new_namespace,
        ip: new_ip,
        http: new_ports.http_port,
        https: new_ports.https_port
    }

    let s = parseJson2Str(data)
    s = s.replace("\n", "")
    execSync(`echo "${s}" > ../ngrok/docker_env_name.sh`)
    cproc.exec("../ngrok/make_frp_ini_V2.sh");
    res.send({ msg: "执行完成" });
});


// 删除一个namespace映射
admin.post('/remove_proxy', function (req, res) {
    let request = req.body;
    console.log(request);
    let new_namespace = request["namespace"];
    var str = String(execSync(`cat ../ngrok/docker_env_name.sh`)).replace(/\n/, "");
    let data = parseStr2Json(str);
    delete data[new_namespace]
    let s = parseJson2Str(data)
    s = s.replace("\n", "")
    execSync(`echo "${s}" > ../ngrok/docker_env_name.sh`)
    cproc.exec("../ngrok/make_frp_ini_V2.sh");
    var last_str = String(execSync(`cat ../ngrok/docker_env_name.sh`))
    res.setHeader("Content-Type", "application/json");
    res.send({
        "details": {
            name_spaces: last_str
        },
        "success": true
    });
});

// 获取现有映射关系
admin.get('/get_proxy', function (req, res) {
    res.setHeader("Content-Type", "application/json");
    var str = execSync(`cat ../ngrok/docker_env_name.sh`)
    res.send({ namespace: String(str) });
});

app.use('/config_server', admin)
console.log("http://192.168.4.3:10088/config_server/get_node_command")
app.listen(10088)
