var fs = require('fs');
var book = require('topsin.excelxs');
var db = require('topsin.database');
var crypto = require('topsin.crypto');
var error = require('topsin.error');

// 读取配置文件
var config = JSON.parse(fs.readFile('./config.json'));

// 主函数
function Main(props){
    // 执行初始化
    this.init();
}
// 初始化方法
Main.prototype.init = function(){
    this.dirlist = this.readDir(config.dirPath, -1)  // 获取文件夹下的文件列表
    if(this.dirlist.length === 0){  // 没有文件就退出
        return
    }
    this.readXlsx(this.dirlist) // 循环读取文件列表
}
// 读取文件夹 获取xlsx
Main.prototype.readDir = function(path){
    return fs.listDir(path).filter(function(v){return v.completeSuffix === "XLSX"})
}
// 循环读取文件列表 
Main.prototype.readXlsx = function(list){
    var that = this
    list.forEach(function(v){
        // 读取excel文件
        that.excelxs(v.dir + '/' + v.name, v.name)
    })
}
// 读取excelxs
Main.prototype.excelxs = function(path,name){
    if(book.open(path)) {
        var sheet = book.getActiveSheet()  // 获取当前表
        if(sheet.isNull()){return}
        // 获取表字段数量
        var keysCount = sheet.getLastCol()
        // 获取字段数组
        this.keys = [] // 存放所有字段
        this.newkeys = []  // (如果有)存放新的字段
        this.attrData = config.dataKeys["attr_data"]  // 存放 attr_data
        for(var i=0;i<keysCount;i++){  // 读取第一行的字段
            if(config.dataKeys[crypto.md5(sheet.getCellValue(0, i))]){  // 如果是之前存在的字段 直接放入keys 以md5加密作为中介
                this.keys.push(config.dataKeys[crypto.md5(sheet.getCellValue(0, i))].dbkey)
            } else {  // 读取不到的字段 可能是attr_data下的 也可能是新增的
                if(!this.attrData[crypto.md5(sheet.getCellValue(0, i))]){  // 在attr_data下读取 不存在的是新增的
                    this.newkeys.push(sheet.getCellValue(0, i)) // 给newkeys添加新增的字段
                }
            }
        }
        this.keys.push('attr_data') // keys添加上 attr_data
        var that = this
        if(this.newkeys.length !== 0){ // 如果有新增的字段 
            this.newkeys.forEach(function(v){
                var mdkey = crypto.md5(v)  // md5状态
                var dbkeyArr = []
                var str = ""
                var tempv = v + " "
                for(var i = 0,len=tempv.length;i<len;i++){  // 数据库字段 命名规则
                    if(/[a-zA-Z]/.test(tempv[i])){
                        str += tempv[i].toLowerCase()
                    } else if(tempv[i] === " " || tempv[i] === "\n"){
                        dbkeyArr.push(str)
                        str = ""
                    } else {
                        i = len
                    }
                }
                var dbkey = dbkeyArr.join("_") 
                dbkey += "_" + mdkey.substr(0,10)
                that.attrData[mdkey] = {  // 内存中的attrData添加新字段的map
                    name:v,
                    dbkey: dbkey
                }
                config.dataKeys["attr_data"][mdkey] = { // 配置里也要添加
                    name:v,
                    dbkey: dbkey
                }
            })
        }
        var datalist = []  // 定义数组 两次循环获取表数据
        for(var j = 1,length = sheet.getLastRow();j<length;j++){
            datalist[j-1] = {}
            datalist[j-1]["attr_data"] = {}  // 对attr_data的处理
            for(var i = 0;i<keysCount;i++){
                // dbkey 是 对应到数据库的key
                var dbkey = config.dataKeys[crypto.md5(sheet.getCellValue(0, i))] ? config.dataKeys[crypto.md5(sheet.getCellValue(0, i))].dbkey : null
                if(dbkey === "posting_date"){  // 对日期的特殊处理
                    datalist[j-1][dbkey] = formatDate(sheet.getCellValue(j, i))
                } else if (dbkey === "confirmation_entry_time") { // 对时间的特殊处理
                    datalist[j-1][dbkey] = formatTime(sheet.getCellValue(j, i))
                } else if(!config.dataKeys[crypto.md5(sheet.getCellValue(0, i))]) { // 对attr_data字段的特殊处理
                    datalist[j-1]["attr_data"][this.attrData[crypto.md5(sheet.getCellValue(0, i))].dbkey] = sheet.getCellValue(j, i)
                } else {
                    datalist[j-1][dbkey] = sheet.getCellValue(j, i)
                }
            }
        }
        // 数据处理
        this.paytionType({
            datalist:datalist
        })
        book.saveAs(config.rdir + '/' + name)  // 读取完的文件另存为 然后可以删除
        // 删除处理过的文件
        fs.unlink(path)
        book.close()
    }
}
Main.prototype.paytionType = function(props){  // 处理数据
    db.addConnection(config.dbconfig, "Scott_PMO_TRAINING");  // 连接数据库
    this.tablename = 'sec_production_order_confirmation_2'  // 设置数据库表名
    this.query = db.query('Scott_PMO_TRAINING');  // 获取操作对象
    var dbDatas = getDbData(this.query,this.tablename)  // 获取数据库的所有数据
    if(!dbDatas){return}
    console.log("数据库的数据数量:" + dbDatas.length)
    if(this.newkeys.length === 0){ // 不存在新的字段 只要新增就行
        // console.log(this.query.deleteRow({
        //     table:'sec_production_order_confirmation_2',
        //     where: ["id >= 0"]
        // }))   // 删除所有数据
        console.log("插入操作");
        var res = this.filterOldData(props.datalist,dbDatas)  // 数据过滤
        var newData = res.newData // 获取要插入的数据
        console.log("新的数据:"+newData.length);
        console.log(newData[0]);
        if(newData.length === 0) {return}
        this.insertAny(newData)  // 插入数据库操作
    } else {  // 对旧的数据执行更新操作 对新的数据执行添加
        console.log('要对字段扩展:')
        var res = this.filterOldData(props.datalist,dbDatas,"newkey")  // 数据过滤 顺便更新旧的数据
        var newData = res.newData // 获取要插入的数据
        console.log("新的数据:"+newData.length);
        console.log(newData[0]);
        // 插入新数据
        if(newData.length === 0) {
            return
        }
        this.insertAny(newData)  // 插入数据库操作
    }

    db.removeConnection('Scott_PMO_TRAINING');  // 移除数据库操作
}
Main.prototype.insertAny = function(datas){ // 批量插入数据
    this.query.begin()
    var that = this
    try{
        this.query.batchInsert(
            that.tablename,
            that.keys,
            datas
        );
        if (this.query.lastError().isValid()){
            throw this.query.lastError().text();
        }
        this.query.commit();
    }
    catch(err) {
        console.log("插入数据错误")
        console.log(err)
        this.query.rollback();
    }
}
function getDbData(query,tablename){   // 获取数据库所有数据
    query.begin();
    var data;
    try {
        data = query.selectArrayMap({
            table: tablename,
            field: '*',
            field_format:{"tags":'array', attr_data:'json'}
        });
        if (query.lastError().isValid()){
            throw query.lastError().text();
        }
        query.commit();
    } catch (error) {
        console.log("获取数据库数据错误");
        console.log(error);
        query.rollback();
        // data = false;
    }
    return data
}
// key过滤  根据唯一的key将数据分为两组 一组是新数据 一组是原来的数据
Main.prototype.filterOldData = function (datas,dbdatas, type){
    var type = type || null
    console.log("type:"+ type)  // 类型 是否执行字段更新操作
    // 获取dbdata的唯一字段列表
    dbI = dbdatas.map(function(v){
        var tempStr = ""
        tempStr += v["confirmation"] + v["plant"] + v["material"] + v["posting_date"] + v["confirmation_entry_time"] + v["activity"]
        return tempStr
    })
    var oldData = [],
        newData = [];
    for(var i = 0,len=datas.length;i<len;i++){
        var v = datas[i]
        var dataI = v["confirmation"] + v["plant"] + v["material"] + v["posting_date"] + v["confirmation_entry_time"] + v["activity"]
        if(dbI.indexOf(dataI) >= 0){
            // 老数据
            var updateData = {}
            if(type === "newkey"){
                updateData["attr_data"] = v["attr_data"]
            }
            // 判断老数据是否更新了
            for(var key in v){
                if(key==="attr_data"){
                    var tempflag = false
                    for(var tempdbkey in dbdatas[dbI.indexOf(dataI)][key]){
                        if(v[key][tempdbkey] && dbdatas[dbI.indexOf(dataI)][key][tempdbkey] != v[key][tempdbkey]){
                            tempflag = true
                        }
                    }
                    if(tempflag){
                        updateData["attr_data"] = v["attr_data"]
                    }
                } else {
                    if(v[key] != dbdatas[dbI.indexOf(dataI)][key]) {
                    updateData[key] = v[key]
                    }
                }
                
            }
            if(JSON.stringify(updateData) !== "{}"){ // 有要更新的情况
                console.log("更新...")
                this.UpdateKeys(updateData,dbdatas[dbI.indexOf(dataI)]["id"])
            }
            oldData.push(v)
        } else{
            // 新数据
            newData.push(v)
        }
    }
    console.log("旧的数据:"+oldData.length)
    console.log(oldData[oldData.length-1]);
    return {
        oldData:oldData,
        newData:newData
    }
}
// 更新数据
Main.prototype.UpdateKeys = function(data,id){
    console.log(data)
    console.log(id)
    // 执行更新操作
    this.query.begin()
    var that = this
    try {
        this.query.updateRow({
            table:that.tablename,
            data:data,
            where:{id:id},
            update_policy:{tags:'array_append', attr_data:'json_merge'}
        })
        if (this.query.lastError().isValid()){
            throw this.query.lastError().text();
        }
        this.query.commit();
    } catch (error) {
        console.log("更新错误")
        console.log(error)
        this.query.rollback();
    }
}
function formatDate(numb) {
    var time = new Date((numb - 1) * 24 * 3600000 + 1)
    time.setYear(time.getFullYear() - 70)
    var year = time.getFullYear() + ''
    var month = time.getMonth() + 1 + ''
    var date = time.getDate() + ''
    return year + "-" + (month<10?"0"+month:month) + "-" + (date<10?"0"+date:date)
}
function formatTime(numb) {
    var hourTmp = numb * 24;
    var hour = Math.floor(hourTmp);
    var minuteTmp = hourTmp - hour;
    var minute = Math.floor(minuteTmp * 60);
    var secondTmp = (minuteTmp*60) - minute;
    var second = Math.round(secondTmp*60);
    if(second >= 60){
        second = 0
        minute += 1
    }
    if(minute >= 60) {
        minute = minute - 60
        hour += 1
    }
    if(hour >= 24) {
        hour = 0
    }
    return (hour<10? "0" + hour : hour) + ":" + (minute<10? "0" + minute : minute) + ":" + (second<10? "0" + second : second) 
}
function configReset(bol){
    config.isUseing = bol
    fs.writeFile('./config.json',JSON.stringify(config)) // 覆盖写入json
}
if(!config.isUseing){  // 如果没在运行程序就可以实例化
    configReset(true) // 状态变成运行中
    var demo = new Main()
    configReset(false)  // 状态变成未运行
}



// ["attr_data","action_data","extra_data","tags","sys_tags","sys_data"]