const mysql = require("mysql2/promise");

class DBPool {
  constructor(coin, options) {
    this.coin = coin;
    this.pool = mysql.createPool(options);
  }

  /**
   * 非事务SQL操作
   * @param {String} sql
   * @param {Array} values
   * @returns
   */
  async exec(sql, values = []) {
    const con = await this.pool.getConnection();
    try {
      const [data] = await con.query(sql, values);
      return data;
    } catch (err) {
      throw err;
    } finally {
      con.release();
    }
  }
  /**
   * 单独SQL事务操作
   * @param {String} sql
   * @param {Array} values
   * @returns
   */
  async exec_transaction(sql, values = []) {
    const con = await this.pool.getConnection();
    try {
      await con.beginTransaction();
      const [data] = await con.query(sql, values);
      await con.commit();
      return data;
    } catch (err) {
      await con.rollback();
      throw err;
    } finally {
      con.release();
    }
  }

  /**
   * 执行一系列 SQL 操作,合并到一个事务中。
   * @param {Array} params [{sql:"", param:[param1, param2, ...]}]
   */
  async exec_transaction_together(params) {
    const con = await this.pool.getConnection();
    try {
      await con.beginTransaction();

      // 确保所有查询都完成后再提交事务
      for (const { sql, param } of params) {
        await con.query(sql, param);
      }

      await con.commit();
    } catch (err) {
      await con.rollback();
      throw err;
    } finally {
      con.release();
    }
  }

  async exec_write_lock(sql, values = [], table_name) {
    const con = await this.pool.getConnection();
    try {
      await con.beginTransaction();
      // 使用模板字符串而不是占位符来构建 LOCK TABLES 语句
      await con.query(`LOCK TABLES ${table_name} WRITE`);
      await con.query(sql, values);
      await con.commit();
    } catch (err) {
      await con.rollback();
      throw err;
    } finally {
      await con.query("UNLOCK TABLES");
      con.release();
    }
  }
}

module.exports = DBPool