const system = require("../system");
class Dao {
  constructor(modelName) {
    this.modelName = modelName;
    var db = system.getObject("db.common.connection").getCon();
    this.db = db;
    console.log("........set dao model..........");
    console.log(this.modelName)
    this.model = db.models[this.modelName];
    console.log(this.modelName);
  }
  preCreate(u) {
    return u;
  }
  async create(u, t) {
    var u2 = this.preCreate(u);
    if (t) {
      console.log(">>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>>");
      console.log( this.model);
      return this.model.create(u2, { transaction: t }).then(u => {
        return u;
      });
    } else {
      return this.model.create(u2).then(u => {
        return u;
      });
    }
  }
  static getModelName(ClassObj) {
    return ClassObj["name"].substring(0, ClassObj["name"].lastIndexOf("Dao")).toLowerCase()
  }
  async refQuery(qobj) {
    var w = qobj.refwhere ? qobj.refwhere : {};
    if (qobj.levelinfo) {
      w[qobj.levelinfo.levelfield] = qobj.levelinfo.level;
    }
    if (qobj.parentinfo) {
      w[qobj.parentinfo.parentfield] = qobj.parentinfo.parentcode;
    }
    //如果需要控制数据权限
    if (qobj.datapriv) {
      w["id"] = { [this.db.Op.in]: qobj.datapriv };
    }
    if (qobj.likestr) {
      w[qobj.fields[0]] = { [this.db.Op.like]: "%" + qobj.likestr + "%" };
      return this.model.findAll({ where: w, attributes: qobj.fields });
    } else {
      return this.model.findAll({ where: w, attributes: qobj.fields });
    }
  }
  async bulkDelete(ids) {
    var en = await this.model.destroy({ where: { id: { [this.db.Op.in]: ids } } });
    return en;
  }
  async bulkDeleteByWhere(whereParam, t) {
    var en = null;
    if (t != null && t != 'undefined') {
      whereParam.transaction = t;
      return await this.model.destroy(whereParam);
    } else {
      return await this.model.destroy(whereParam);
    }
  }
  async delete(qobj, t) {
    var en = null
    if (t != null && t != 'undefined') {
      en = await this.model.findOne({ where: { id: qobj.id }, transaction: t });
      if (en != null) {
        await en.destroy({ transaction: t });
        return en
      }
    } else {
      en = await this.model.findOne({ where: { id: qobj.id } });
      if (en != null) {
        return en.destroy();
      }
      return en
    }
  }
  extraModelFilter(pobj) {
    //return {"key":"include","value":{model:this.db.models.app}};
    return null;
  }
  extraWhere(obj, where) {
    return where;
  }
  orderBy() {
    //return {"key":"include","value":{model:this.db.models.app}};
    return [["created_at", "DESC"]];
  }
  buildQuery(qobj) {
    var linkAttrs = [];
    const pageNo = qobj.pageInfo.pageNo;
    const pageSize = qobj.pageInfo.pageSize;
    const search = qobj.search;
    var qc = {};
    //设置分页查询条件
    qc.limit = pageSize;
    qc.offset = (pageNo - 1) * pageSize;
    //默认的查询排序
    qc.order = this.orderBy();
    //构造where条件
    qc.where = {};
    if (search) {
      Object.keys(search).forEach(k => {
        console.log(search[k], ":search[k]search[k]search[k]");
        if (search[k] && search[k] != 'undefined' && search[k] != "") {
          if ((k.indexOf("Date") >= 0 || k.indexOf("_at") >= 0)) {
            if (search[k] != "" && search[k]) {
              var stdate = new Date(search[k][0]);
              var enddate = new Date(search[k][1]);
              qc.where[k] = { [this.db.Op.between]: [stdate, enddate] };
            }
          }
          else if (k.indexOf("id") >= 0) {
            qc.where[k] = search[k];
          }
          else if (k.indexOf("channelCode") >= 0) {
            qc.where[k] = search[k];
          }
          else if (k.indexOf("Type") >= 0) {
            qc.where[k] = search[k];
          }
          else if (k.indexOf("Status") >= 0) {
            qc.where[k] = search[k];
          }
          else if (k.indexOf("status") >= 0) {
            qc.where[k] = search[k];
          }
          else {
            if (k.indexOf("~") >= 0) {
              linkAttrs.push(k);
            } else {
              qc.where[k] = { [this.db.Op.like]: "%" + search[k] + "%" };
            }
          }
        }
      });
    }
    this.extraWhere(qobj, qc.where, qc, linkAttrs);
    var extraFilter = this.extraModelFilter(qobj);
    if (extraFilter) {
      qc[extraFilter.key] = extraFilter.value;
    }
    console.log("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmmm");
    console.log(qc);
    return qc;
  }
  buildaggs(qobj) {
    var aggsinfos = [];
    if (qobj.aggsinfo) {
      qobj.aggsinfo.sum.forEach(aggitem => {
        var t1 = [this.db.fn('SUM', this.db.col(aggitem.field)), aggitem.field + "~" + "sum"];
        aggsinfos.push(t1);
      });
      qobj.aggsinfo.avg.forEach(aggitem => {
        var t2 = [this.db.fn('AVG', this.db.col(aggitem.field)), aggitem.field + "~" + "avg"];
        aggsinfos.push(t2);
      });
    }
    return aggsinfos;
  }
  async findAggs(qobj, qcwhere) {
    var aggArray = this.buildaggs(qobj);
    if (aggArray.length != 0) {
      qcwhere["attributes"] = {};
      qcwhere["attributes"] = aggArray;
      qcwhere["raw"] = true;
      var aggResult = await this.model.findOne(qcwhere);
      return aggResult;
    } else {
      return {};
    }

  }
  async findAndCountAll(qobj, t) {
    var qc = this.buildQuery(qobj);
    var apps = await this.model.findAndCountAll(qc);
    var aggresult = await this.findAggs(qobj, qc);
    var rtn = {};
    rtn.results = apps;
    rtn.aggresult = aggresult;
    return rtn;
  }
  preUpdate(obj) {
    return obj;
  }
  async update(obj, tm) {
    var obj2 = this.preUpdate(obj);
    if (tm != null && tm != 'undefined') {
      return this.model.update(obj2, { where: { id: obj2.id }, transaction: tm });
    } else {
      return this.model.update(obj2, { where: { id: obj2.id } });
    }
  }
  async bulkCreate(ids, t) {
    if (t != null && t != 'undefined') {
      return await this.model.bulkCreate(ids, { transaction: t });
    } else {
      return await this.model.bulkCreate(ids);
    }
  }

  async updateByWhere(setObj, whereObj, t) {
    let inWhereObj = {}
    if (t && t != 'undefined') {
      if (whereObj && whereObj != 'undefined') {
        inWhereObj["where"] = whereObj;
        inWhereObj["transaction"] = t;
      } else {
        inWhereObj["transaction"] = t;
      }
    } else {
      inWhereObj["where"] = whereObj;
    }
    return this.model.update(setObj, inWhereObj);
  }
  async customExecAddOrPutSql(sql, paras = null) {
    return this.db.query(sql, paras);
  }
  /**
   * p.group.fields=['','']
   * p.group.sumField=''
   * p.group.aliasField=' as xxx'
   * @param {*} p 
   */
  async statGroupBy(p, paras, t) {
    let groupFields = p.group.byFields.join(",")
    let aggField = p.group.aggField ? p.group.aggField : ''
    let tblName = p.group.tblName ? p.group.tblName : ''
    let where = p.group.where ? p.group.where : ''
    let having = p.group.having ? p.group.having : ''
    let aliasField = p.group.aliasField ? p.group.aliasField : ''
    let actionType = p.group.actionType ? p.group.actionType : 'count'
    let sql = `select ${groupFields},${actionType}(${aggField})  ${aliasField} from ${tblName}  ${where}  group by ${groupFields} ${having}  WITH ROLLUP`
    return this.customQuery(sql, paras, t)
  }

  async customQuery(sql, paras, t) {
    var tmpParas = null;//||paras=='undefined'?{type: this.db.QueryTypes.SELECT }:{ replacements: paras, type: this.db.QueryTypes.SELECT };
    if (t && t != 'undefined') {
      if (paras == null || paras == 'undefined') {
        tmpParas = { type: this.db.QueryTypes.SELECT };
        tmpParas.transaction = t;
      } else {
        tmpParas = { replacements: paras, type: this.db.QueryTypes.SELECT };
        tmpParas.transaction = t;
      }
    } else {
      tmpParas = paras == null || paras == 'undefined' ? { type: this.db.QueryTypes.SELECT } : { replacements: paras, type: this.db.QueryTypes.SELECT };
    }
    return this.db.query(sql, tmpParas);
  }
  async findCount(whereObj = null) {
    return this.model.count(whereObj, { logging: false }).then(c => {
      return c;
    });
  }
  async findSum(fieldName, whereObj = null) {
    return this.model.sum(fieldName, whereObj);
  }
  async getPageList(pageIndex, pageSize, whereObj = null, orderObj = null, attributesObj = null, includeObj = null) {
    var tmpWhere = {};
    tmpWhere.limit = pageSize;
    tmpWhere.offset = (pageIndex - 1) * pageSize;
    if (whereObj != null) {
      tmpWhere.where = whereObj;
    }
    if (orderObj != null && orderObj.length > 0) {
      tmpWhere.order = orderObj;
    }
    if (attributesObj != null && attributesObj.length > 0) {
      tmpWhere.attributes = attributesObj;
    }
    if (includeObj != null && includeObj.length > 0) {
      tmpWhere.include = includeObj;
      tmpWhere.distinct = true;
    } else {
      tmpWhere.raw = true;
    }
    return await this.model.findAndCountAll(tmpWhere);
  }
  async findOne(obj) {
    return this.model.findOne({ "where": obj });
  }
  async findById(oid) {
    return this.model.findById(oid);
  }
  async findAll(obj, include = []) {
    return this.model.findAll({ "where": obj, include, row: true });
  }
}
module.exports = Dao;
