function formatDate(date) {
  const year = date.getFullYear();
  const month = String(date.getMonth() + 1).padStart(2, "0");
  const day = String(date.getDate()).padStart(2, "0");
  const hours = String(date.getHours()).padStart(2, "0");
  const minutes = String(date.getMinutes()).padStart(2, "0");
  const seconds = String(date.getSeconds()).padStart(2, "0");

  return `${year}-${month}-${day} ${hours}:${minutes}:${seconds}`;
}
class GormCommonClass {
  constructor(props) {
    this.wheres = [];
    this.values = [];
    this.tabName = props.tabName;
  }

  getWhereStr() {
    if (this.wheres.length) {
      return ` WHERE ${this.wheres.join(" AND ")}`;
    }
    return "";
  }

  where(w, ...vals) {
    this.wheres.push(w);
    this.values.push(...vals);
    return this;
  }

  verifyLen(sql, vals) {
    const wLen = sql.split("?")?.length - 1;

    if (wLen != vals.length) {
      throw "占位符与值的数量不匹配";
    }
  }
}

class GormSelectClass extends GormCommonClass {
  #selectKeys = [];
  #tabName = "";

  #offset;
  #limit = 1;

  #groupBys = [];
  #orderBys = [];

  constructor(props) {
    super(props);
    this.#selectKeys = props.selectKeys;
    this.#tabName = props.tabName;
  }

  where(w, ...vals) {
    this.wheres.push(w);
    this.values.push(...vals);
    return this;
  }

  offset(val) {
    this.#offset = Number(val) || 0;
    return this;
  }

  limit(val) {
    this.#limit = Number(val) || 1;
    return this;
  }

  orderBy(orderKey, sort) {
    this.#orderBys.push(`${orderKey} ${sort}`);
    return this;
  }
  groupBy(...agrs) {
    this.#groupBys.push(...agrs);
    return this;
  }

  build() {
    let sqlStr = `SELECT ${this.#selectKeys.join(",")} FROM ${this.#tabName}`;

    sqlStr += this.getWhereStr();

    if (this.#groupBys.length) {
      sqlStr += " GROUP BY ";
      sqlStr += this.#groupBys.join(", ");
    }

    if (this.#orderBys.length) {
      sqlStr += " ORDER BY ";
      sqlStr += this.#orderBys.join(", ");
    }

    if (this.#limit) {
      sqlStr += ` LIMIT ${this.#limit}`;
    }
    if (this.#offset) {
      sqlStr += ` OFFSET ${this.#offset}`;
    }

    this.verifyLen(sqlStr, this.values);

    return {
      sql: sqlStr,
      values: this.values,
    };
  }
}

class GormUpdateClass extends GormCommonClass {
  #tabName = "";

  #updateList = [];

  constructor(props) {
    super(props);

    this.#tabName = props.tabName;
    this.#init(props.updateData || {});
  }

  #init(updateData) {
    const updateKeys = Object.keys(updateData);

    if (!updateKeys.length) {
      throw "没有需要修改的key";
    }

    for (const key of updateKeys) {
      this.#updateList.push(`${key} = ?`);

      let data = updateData[key];

      if (typeof data == "object" && data != null && !(data instanceof Date)) {
        data = JSON.stringify(data);
      }

      if (data instanceof Date) {
        data = formatDate(data);
      }

      this.values.push(data || null);
    }
  }

  where(w, ...vals) {
    this.wheres.push(w);
    this.values.push(...vals);
    return this;
  }

  build() {
    let sqlStr = `UPDATE ${this.#tabName}`;

    if (!this.#updateList) {
      throw "没有需要修改的key";
    }

    if (!this.wheres.length) {
      throw "修改数据必须指定条件";
    }

    sqlStr += " SET ";

    sqlStr += this.#updateList.join(", ");

    sqlStr += this.getWhereStr();

    this.verifyLen(sqlStr, this.values);

    return {
      sql: sqlStr,
      values: this.values,
    };
  }
}

class GormInsertClass {
  #insertKeys = [];
  #tabName = "";

  #values = [];

  constructor(props) {
    this.#tabName = props.tabName;

    this.#init(props.insertData);
  }

  #init(insertData) {
    const insertKeys = Object.keys(insertData);
    if (!insertKeys.length) {
      throw "没有需要插入的key";
    }

    this.#insertKeys = insertKeys;

    for (const key of insertKeys) {
      let data = insertData[key];

      if (typeof data == "object" && data != null && !(data instanceof Date)) {
        data = JSON.stringify(data);
      }

      if (data instanceof Date) {
        data = formatDate(data);
      }

      this.#values.push(data || null);
    }
  }

  verifyLen(sql, vals) {
    const wLen = sql.split("?")?.length - 1;

    if (wLen != vals.length) {
      throw "占位符与值的数量不匹配";
    }
  }

  build() {
    let sqlStr = `INSERT INTO ${this.#tabName} (${this.#insertKeys.join(
      ", "
    )})`;
    sqlStr += ` VALUES (${this.#insertKeys.map(() => "?").join(", ")})`;

    this.verifyLen(sqlStr, this.#values);

    return {
      sql: sqlStr,
      values: this.#values,
    };
  }
}

class GormClass {
  #props;
  constructor(props) {
    this.#props = props;
  }

  select(...selectKeys) {
    return new GormSelectClass({ ...this.#props, selectKeys });
  }

  update(updateData) {
    return new GormUpdateClass({ ...this.#props, updateData });
  }

  delete() {
    return new GormUpdateClass({
      ...this.#props,
      updateData: { delete_time: new Date() },
    });
  }

  insert(insertData) {
    return new GormInsertClass({ ...this.#props, insertData });
  }
}
