package com.ustadmobile.core.db.dao

import androidx.paging.PagingSource
import com.ustadmobile.door.DoorDbType
import com.ustadmobile.door.EntityInsertionAdapter
import com.ustadmobile.door.PreparedStatementConfig
import com.ustadmobile.door.ext.prepareAndUseStatement
import com.ustadmobile.door.ext.prepareAndUseStatementAsync
import com.ustadmobile.door.flow.doorFlow
import com.ustadmobile.door.jdbc.PreparedStatement
import com.ustadmobile.door.jdbc.ext.executeQueryAsyncKmp
import com.ustadmobile.door.jdbc.ext.executeUpdateAsyncKmp
import com.ustadmobile.door.jdbc.ext.getStringNonNull
import com.ustadmobile.door.jdbc.ext.mapNextRow
import com.ustadmobile.door.jdbc.ext.mapRows
import com.ustadmobile.door.jdbc.ext.useResults
import com.ustadmobile.door.paging.DoorLimitOffsetPagingSource
import com.ustadmobile.door.room.RoomDatabase
import com.ustadmobile.lib.db.composites.ClazzInviteAndClazz
import com.ustadmobile.lib.db.composites.ClazzInviteWithTimeZone
import com.ustadmobile.lib.db.entities.Clazz
import com.ustadmobile.lib.db.entities.ClazzInvite
import kotlin.Boolean
import kotlin.Int
import kotlin.Long
import kotlin.String
import kotlin.collections.List
import kotlinx.coroutines.flow.Flow

public class ClazzInviteDao_JdbcImpl(
  public val _db: RoomDatabase,
) : ClazzInviteDao() {
  public val _insertAdapterClazzInvite_upsert: EntityInsertionAdapter<ClazzInvite> = object :
      EntityInsertionAdapter<ClazzInvite>(_db) {
    override fun makeSql(returnsId: Boolean): String =
        "INSERT OR REPLACE INTO ClazzInvite (ciUid, ciPersonUid, ciRoleId, ciClazzUid, inviteType, inviteContact, inviteToken, inviteStatus, inviteExpire, inviteLct) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"

    override fun bindPreparedStmtToEntity(stmt: PreparedStatement, entity: ClazzInvite) {
      if(entity.ciUid == 0L) {
        stmt.setObject(1, null)
      } else {
        stmt.setLong(1, entity.ciUid)
      }
      stmt.setLong(2, entity.ciPersonUid)
      stmt.setLong(3, entity.ciRoleId)
      stmt.setLong(4, entity.ciClazzUid)
      stmt.setInt(5, entity.inviteType)
      stmt.setString(6, entity.inviteContact)
      stmt.setString(7, entity.inviteToken)
      stmt.setInt(8, entity.inviteStatus)
      stmt.setLong(9, entity.inviteExpire)
      stmt.setLong(10, entity.inviteLct)
    }
  }

  public val _insertAdapterClazzInvite_ignore: EntityInsertionAdapter<ClazzInvite> = object :
      EntityInsertionAdapter<ClazzInvite>(_db) {
    override fun makeSql(returnsId: Boolean): String =
        "INSERT  OR IGNORE INTO ClazzInvite (ciUid, ciPersonUid, ciRoleId, ciClazzUid, inviteType, inviteContact, inviteToken, inviteStatus, inviteExpire, inviteLct) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"

    override fun bindPreparedStmtToEntity(stmt: PreparedStatement, entity: ClazzInvite) {
      if(entity.ciUid == 0L) {
        stmt.setObject(1, null)
      } else {
        stmt.setLong(1, entity.ciUid)
      }
      stmt.setLong(2, entity.ciPersonUid)
      stmt.setLong(3, entity.ciRoleId)
      stmt.setLong(4, entity.ciClazzUid)
      stmt.setInt(5, entity.inviteType)
      stmt.setString(6, entity.inviteContact)
      stmt.setString(7, entity.inviteToken)
      stmt.setInt(8, entity.inviteStatus)
      stmt.setLong(9, entity.inviteExpire)
      stmt.setLong(10, entity.inviteLct)
    }
  }

  public val _insertAdapterClazzInvite_abort: EntityInsertionAdapter<ClazzInvite> = object :
      EntityInsertionAdapter<ClazzInvite>(_db) {
    override fun makeSql(returnsId: Boolean): String =
        "INSERT INTO ClazzInvite (ciUid, ciPersonUid, ciRoleId, ciClazzUid, inviteType, inviteContact, inviteToken, inviteStatus, inviteExpire, inviteLct) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"

    override fun bindPreparedStmtToEntity(stmt: PreparedStatement, entity: ClazzInvite) {
      if(entity.ciUid == 0L) {
        stmt.setObject(1, null)
      } else {
        stmt.setLong(1, entity.ciUid)
      }
      stmt.setLong(2, entity.ciPersonUid)
      stmt.setLong(3, entity.ciRoleId)
      stmt.setLong(4, entity.ciClazzUid)
      stmt.setInt(5, entity.inviteType)
      stmt.setString(6, entity.inviteContact)
      stmt.setString(7, entity.inviteToken)
      stmt.setInt(8, entity.inviteStatus)
      stmt.setLong(9, entity.inviteExpire)
      stmt.setLong(10, entity.inviteLct)
    }
  }

  override suspend fun replace(entity: ClazzInvite): Long {
    val _retVal = _insertAdapterClazzInvite_upsert.insertAndReturnIdAsync(entity)
    return _retVal
  }

  override suspend fun insertAll(entity: List<ClazzInvite>) {
    _insertAdapterClazzInvite_ignore.insertListAsync(entity)
  }

  public override fun insert(entity: ClazzInvite): Long {
    val _retVal = _insertAdapterClazzInvite_abort.insertAndReturnId(entity)
    return _retVal
  }

  public override suspend fun insertAsync(entity: ClazzInvite): Long {
    val _retVal = _insertAdapterClazzInvite_abort.insertAndReturnIdAsync(entity)
    return _retVal
  }

  public override fun insertList(entityList: List<ClazzInvite>) {
    _insertAdapterClazzInvite_abort.insertList(entityList)
  }

  override suspend fun updateAll(entity: List<ClazzInvite>) {
    val _sql =
        "UPDATE ClazzInvite SET ciPersonUid = ?, ciRoleId = ?, ciClazzUid = ?, inviteType = ?, inviteContact = ?, inviteToken = ?, inviteStatus = ?, inviteExpire = ?, inviteLct = ? WHERE ciUid = ?"
    _db.prepareAndUseStatementAsync(_sql) {
       _stmt ->
      _stmt.getConnection().setAutoCommit(false)
      for(_entity in entity) {
        _stmt.setLong(1, _entity.ciPersonUid)
        _stmt.setLong(2, _entity.ciRoleId)
        _stmt.setLong(3, _entity.ciClazzUid)
        _stmt.setInt(4, _entity.inviteType)
        _stmt.setString(5, _entity.inviteContact)
        _stmt.setString(6, _entity.inviteToken)
        _stmt.setInt(7, _entity.inviteStatus)
        _stmt.setLong(8, _entity.inviteExpire)
        _stmt.setLong(9, _entity.inviteLct)
        _stmt.setLong(10, _entity.ciUid)
        _stmt.executeUpdateAsyncKmp()
      }
      _stmt.getConnection().commit()
    }
  }

  public override fun update(entity: ClazzInvite) {
    val _sql =
        "UPDATE ClazzInvite SET ciPersonUid = ?, ciRoleId = ?, ciClazzUid = ?, inviteType = ?, inviteContact = ?, inviteToken = ?, inviteStatus = ?, inviteExpire = ?, inviteLct = ? WHERE ciUid = ?"
    _db.prepareAndUseStatement(_sql) {
       _stmt ->
      _stmt.setLong(1, entity.ciPersonUid)
      _stmt.setLong(2, entity.ciRoleId)
      _stmt.setLong(3, entity.ciClazzUid)
      _stmt.setInt(4, entity.inviteType)
      _stmt.setString(5, entity.inviteContact)
      _stmt.setString(6, entity.inviteToken)
      _stmt.setInt(7, entity.inviteStatus)
      _stmt.setLong(8, entity.inviteExpire)
      _stmt.setLong(9, entity.inviteLct)
      _stmt.setLong(10, entity.ciUid)
      _stmt.executeUpdate()
    }
  }

  override suspend fun findInviteAsync(): List<ClazzInvite> =
      _db.prepareAndUseStatementAsync(PreparedStatementConfig(
    sql = "SELECT * FROM ClazzInvite",
    readOnly = true,)
  ) { _stmt -> 
    _stmt.executeQueryAsyncKmp().useResults{ _result -> 
      _result.mapRows {
        val _tmp_ciUid = _result.getLong("ciUid")
        val _tmp_ciPersonUid = _result.getLong("ciPersonUid")
        val _tmp_ciRoleId = _result.getLong("ciRoleId")
        val _tmp_ciClazzUid = _result.getLong("ciClazzUid")
        val _tmp_inviteType = _result.getInt("inviteType")
        val _tmp_inviteContact = _result.getStringNonNull("inviteContact")
        val _tmp_inviteToken = _result.getStringNonNull("inviteToken")
        val _tmp_inviteStatus = _result.getInt("inviteStatus")
        val _tmp_inviteExpire = _result.getLong("inviteExpire")
        val _tmp_inviteLct = _result.getLong("inviteLct")
        ClazzInvite().apply {
          this.ciUid = _tmp_ciUid
          this.ciPersonUid = _tmp_ciPersonUid
          this.ciRoleId = _tmp_ciRoleId
          this.ciClazzUid = _tmp_ciClazzUid
          this.inviteType = _tmp_inviteType
          this.inviteContact = _tmp_inviteContact
          this.inviteToken = _tmp_inviteToken
          this.inviteStatus = _tmp_inviteStatus
          this.inviteExpire = _tmp_inviteExpire
          this.inviteLct = _tmp_inviteLct
        }
      }
    }
  }

  override suspend fun findClazzInviteEntityForInviteToken(inviteTokenUid: String):
      ClazzInviteWithTimeZone? = _db.prepareAndUseStatementAsync(PreparedStatementConfig(
    sql = """
    |
    |    SELECT ClazzInvite.*, 
    |           COALESCE(Clazz.clazzTimeZone, 'UTC') AS timeZone
    |      FROM ClazzInvite
    |           LEFT JOIN Clazz 
    |                     ON Clazz.clazzUid = ClazzInvite.ciClazzUid
    |     WHERE ClazzInvite.inviteToken = ?
    |""".trimMargin(),
    readOnly = true,)
  ) { _stmt -> 
    _stmt.setString(1,inviteTokenUid)
    _stmt.executeQueryAsyncKmp().useResults{ _result -> 
      _result.mapNextRow(null) {
        val _tmp_timeZone = _result.getString("timeZone")
        var _tmp_ClazzInvite_nullCount = 0
        val _tmp_ciUid = _result.getLong("ciUid")
        if(_result.wasNull()) _tmp_ClazzInvite_nullCount++
        val _tmp_ciPersonUid = _result.getLong("ciPersonUid")
        if(_result.wasNull()) _tmp_ClazzInvite_nullCount++
        val _tmp_ciRoleId = _result.getLong("ciRoleId")
        if(_result.wasNull()) _tmp_ClazzInvite_nullCount++
        val _tmp_ciClazzUid = _result.getLong("ciClazzUid")
        if(_result.wasNull()) _tmp_ClazzInvite_nullCount++
        val _tmp_inviteType = _result.getInt("inviteType")
        if(_result.wasNull()) _tmp_ClazzInvite_nullCount++
        val _tmp_inviteContact = _result.getStringNonNull("inviteContact")
        if(_result.wasNull()) _tmp_ClazzInvite_nullCount++
        val _tmp_inviteToken = _result.getStringNonNull("inviteToken")
        if(_result.wasNull()) _tmp_ClazzInvite_nullCount++
        val _tmp_inviteStatus = _result.getInt("inviteStatus")
        if(_result.wasNull()) _tmp_ClazzInvite_nullCount++
        val _tmp_inviteExpire = _result.getLong("inviteExpire")
        if(_result.wasNull()) _tmp_ClazzInvite_nullCount++
        val _tmp_inviteLct = _result.getLong("inviteLct")
        if(_result.wasNull()) _tmp_ClazzInvite_nullCount++
        val _tmp_ClazzInvite_isAllNull = _tmp_ClazzInvite_nullCount == 10
        ClazzInviteWithTimeZone().apply {
          this.timeZone = _tmp_timeZone
          if(!_tmp_ClazzInvite_isAllNull) {
            this.clazzInvite = ClazzInvite().apply {
              this.ciUid = _tmp_ciUid
              this.ciPersonUid = _tmp_ciPersonUid
              this.ciRoleId = _tmp_ciRoleId
              this.ciClazzUid = _tmp_ciClazzUid
              this.inviteType = _tmp_inviteType
              this.inviteContact = _tmp_inviteContact
              this.inviteToken = _tmp_inviteToken
              this.inviteStatus = _tmp_inviteStatus
              this.inviteExpire = _tmp_inviteExpire
              this.inviteLct = _tmp_inviteLct
            }
          }
        }
      }
    }
  }

  override fun findClazzInviteEntityForInviteTokenAsFlow(inviteTokenUid: String):
      Flow<ClazzInviteAndClazz?> = _db.doorFlow(arrayOf("ClazzInvite", "Clazz")) {
    _db.prepareAndUseStatementAsync(PreparedStatementConfig(
      sql = """
      |
      |    SELECT ClazzInvite.*, Clazz.*
      |      FROM ClazzInvite
      |           JOIN Clazz 
      |                ON Clazz.clazzUid = ClazzInvite.ciClazzUid
      |     WHERE ClazzInvite.inviteToken = ?
      |    
      """.trimMargin(),
      readOnly = true,)
    ) { _stmt -> 
      _stmt.setString(1,inviteTokenUid)
      _stmt.executeQueryAsyncKmp().useResults{ _result -> 
        _result.mapNextRow(null) {
          var _tmp_ClazzInvite_nullCount = 0
          val _tmp_ciUid = _result.getLong("ciUid")
          if(_result.wasNull()) _tmp_ClazzInvite_nullCount++
          val _tmp_ciPersonUid = _result.getLong("ciPersonUid")
          if(_result.wasNull()) _tmp_ClazzInvite_nullCount++
          val _tmp_ciRoleId = _result.getLong("ciRoleId")
          if(_result.wasNull()) _tmp_ClazzInvite_nullCount++
          val _tmp_ciClazzUid = _result.getLong("ciClazzUid")
          if(_result.wasNull()) _tmp_ClazzInvite_nullCount++
          val _tmp_inviteType = _result.getInt("inviteType")
          if(_result.wasNull()) _tmp_ClazzInvite_nullCount++
          val _tmp_inviteContact = _result.getStringNonNull("inviteContact")
          if(_result.wasNull()) _tmp_ClazzInvite_nullCount++
          val _tmp_inviteToken = _result.getStringNonNull("inviteToken")
          if(_result.wasNull()) _tmp_ClazzInvite_nullCount++
          val _tmp_inviteStatus = _result.getInt("inviteStatus")
          if(_result.wasNull()) _tmp_ClazzInvite_nullCount++
          val _tmp_inviteExpire = _result.getLong("inviteExpire")
          if(_result.wasNull()) _tmp_ClazzInvite_nullCount++
          val _tmp_inviteLct = _result.getLong("inviteLct")
          if(_result.wasNull()) _tmp_ClazzInvite_nullCount++
          val _tmp_ClazzInvite_isAllNull = _tmp_ClazzInvite_nullCount == 10
          var _tmp_Clazz_nullCount = 0
          val _tmp_clazzUid = _result.getLong("clazzUid")
          if(_result.wasNull()) _tmp_Clazz_nullCount++
          val _tmp_clazzName = _result.getString("clazzName")
          if(_result.wasNull()) _tmp_Clazz_nullCount++
          val _tmp_clazzDesc = _result.getString("clazzDesc")
          if(_result.wasNull()) _tmp_Clazz_nullCount++
          val _tmp_attendanceAverage = _result.getFloat("attendanceAverage")
          if(_result.wasNull()) _tmp_Clazz_nullCount++
          val _tmp_clazzHolidayUMCalendarUid = _result.getLong("clazzHolidayUMCalendarUid")
          if(_result.wasNull()) _tmp_Clazz_nullCount++
          val _tmp_clazzScheuleUMCalendarUid = _result.getLong("clazzScheuleUMCalendarUid")
          if(_result.wasNull()) _tmp_Clazz_nullCount++
          val _tmp_isClazzActive = _result.getBoolean("isClazzActive")
          if(_result.wasNull()) _tmp_Clazz_nullCount++
          val _tmp_clazzLocationUid = _result.getLong("clazzLocationUid")
          if(_result.wasNull()) _tmp_Clazz_nullCount++
          val _tmp_clazzStartTime = _result.getLong("clazzStartTime")
          if(_result.wasNull()) _tmp_Clazz_nullCount++
          val _tmp_clazzEndTime = _result.getLong("clazzEndTime")
          if(_result.wasNull()) _tmp_Clazz_nullCount++
          val _tmp_clazzFeatures = _result.getLong("clazzFeatures")
          if(_result.wasNull()) _tmp_Clazz_nullCount++
          val _tmp_clazzSchoolUid = _result.getLong("clazzSchoolUid")
          if(_result.wasNull()) _tmp_Clazz_nullCount++
          val _tmp_clazzEnrolmentPolicy = _result.getInt("clazzEnrolmentPolicy")
          if(_result.wasNull()) _tmp_Clazz_nullCount++
          val _tmp_clazzTerminologyUid = _result.getLong("clazzTerminologyUid")
          if(_result.wasNull()) _tmp_Clazz_nullCount++
          val _tmp_clazzMasterChangeSeqNum = _result.getLong("clazzMasterChangeSeqNum")
          if(_result.wasNull()) _tmp_Clazz_nullCount++
          val _tmp_clazzLocalChangeSeqNum = _result.getLong("clazzLocalChangeSeqNum")
          if(_result.wasNull()) _tmp_Clazz_nullCount++
          val _tmp_clazzLastChangedBy = _result.getInt("clazzLastChangedBy")
          if(_result.wasNull()) _tmp_Clazz_nullCount++
          val _tmp_clazzLct = _result.getLong("clazzLct")
          if(_result.wasNull()) _tmp_Clazz_nullCount++
          val _tmp_clazzTimeZone = _result.getString("clazzTimeZone")
          if(_result.wasNull()) _tmp_Clazz_nullCount++
          val _tmp_clazzStudentsPersonGroupUid = _result.getLong("clazzStudentsPersonGroupUid")
          if(_result.wasNull()) _tmp_Clazz_nullCount++
          val _tmp_clazzTeachersPersonGroupUid = _result.getLong("clazzTeachersPersonGroupUid")
          if(_result.wasNull()) _tmp_Clazz_nullCount++
          val _tmp_clazzPendingStudentsPersonGroupUid =
              _result.getLong("clazzPendingStudentsPersonGroupUid")
          if(_result.wasNull()) _tmp_Clazz_nullCount++
          val _tmp_clazzParentsPersonGroupUid = _result.getLong("clazzParentsPersonGroupUid")
          if(_result.wasNull()) _tmp_Clazz_nullCount++
          val _tmp_clazzCode = _result.getString("clazzCode")
          if(_result.wasNull()) _tmp_Clazz_nullCount++
          val _tmp_clazzOwnerPersonUid = _result.getLong("clazzOwnerPersonUid")
          if(_result.wasNull()) _tmp_Clazz_nullCount++
          val _tmp_Clazz_isAllNull = _tmp_Clazz_nullCount == 25
          ClazzInviteAndClazz().apply {
            if(!_tmp_ClazzInvite_isAllNull) {
              this.clazzInvite = ClazzInvite().apply {
                this.ciUid = _tmp_ciUid
                this.ciPersonUid = _tmp_ciPersonUid
                this.ciRoleId = _tmp_ciRoleId
                this.ciClazzUid = _tmp_ciClazzUid
                this.inviteType = _tmp_inviteType
                this.inviteContact = _tmp_inviteContact
                this.inviteToken = _tmp_inviteToken
                this.inviteStatus = _tmp_inviteStatus
                this.inviteExpire = _tmp_inviteExpire
                this.inviteLct = _tmp_inviteLct
              }
            }
            if(!_tmp_Clazz_isAllNull) {
              this.clazz = Clazz().apply {
                this.clazzUid = _tmp_clazzUid
                this.clazzName = _tmp_clazzName
                this.clazzDesc = _tmp_clazzDesc
                this.attendanceAverage = _tmp_attendanceAverage
                this.clazzHolidayUMCalendarUid = _tmp_clazzHolidayUMCalendarUid
                this.clazzScheuleUMCalendarUid = _tmp_clazzScheuleUMCalendarUid
                this.isClazzActive = _tmp_isClazzActive
                this.clazzLocationUid = _tmp_clazzLocationUid
                this.clazzStartTime = _tmp_clazzStartTime
                this.clazzEndTime = _tmp_clazzEndTime
                this.clazzFeatures = _tmp_clazzFeatures
                this.clazzSchoolUid = _tmp_clazzSchoolUid
                this.clazzEnrolmentPolicy = _tmp_clazzEnrolmentPolicy
                this.clazzTerminologyUid = _tmp_clazzTerminologyUid
                this.clazzMasterChangeSeqNum = _tmp_clazzMasterChangeSeqNum
                this.clazzLocalChangeSeqNum = _tmp_clazzLocalChangeSeqNum
                this.clazzLastChangedBy = _tmp_clazzLastChangedBy
                this.clazzLct = _tmp_clazzLct
                this.clazzTimeZone = _tmp_clazzTimeZone
                this.clazzStudentsPersonGroupUid = _tmp_clazzStudentsPersonGroupUid
                this.clazzTeachersPersonGroupUid = _tmp_clazzTeachersPersonGroupUid
                this.clazzPendingStudentsPersonGroupUid = _tmp_clazzPendingStudentsPersonGroupUid
                this.clazzParentsPersonGroupUid = _tmp_clazzParentsPersonGroupUid
                this.clazzCode = _tmp_clazzCode
                this.clazzOwnerPersonUid = _tmp_clazzOwnerPersonUid
              }
            }
          }
        }
      }
    }
  }

  override suspend fun updateInviteStatus(
    status: Int,
    ciUid: Long,
    updateTime: Long,
  ) {
    _db.prepareAndUseStatementAsync(PreparedStatementConfig(
      sql = """
      |
      |        UPDATE ClazzInvite 
      |           SET inviteStatus = ?,
      |               inviteLct = CAST(? AS BIGINT)
      |         WHERE ClazzInvite.ciUid =CAST(? AS BIGINT)
      |    
      """.trimMargin(),
      postgreSql = """
      |
      |        UPDATE ClazzInvite 
      |           SET inviteStatus = ?,
      |               inviteLct = ?
      |         WHERE ClazzInvite.ciUid =?
      |    
      |""".trimMargin(),
      readOnly = false,)
    ) { _stmt -> 
      _stmt.setInt(1,status)
      _stmt.setLong(2,updateTime)
      _stmt.setLong(3,ciUid)
      _stmt.executeUpdateAsyncKmp()
    }
  }

  override fun findPendingInviteByPersonUid(
    ciPersonUid: Long,
    clazzUid: Long,
    currentTime: Long,
  ): PagingSource<Int, ClazzInvite> = object : DoorLimitOffsetPagingSource<ClazzInvite>(db = _db
  , tableNames = arrayOf("ClazzInvite")
  ) {
    override suspend fun loadRows(_limit: Int, _offset: Int): List<ClazzInvite> =
        _db.prepareAndUseStatementAsync(PreparedStatementConfig(
      sql = """
      |SELECT * FROM (SELECT * FROM ClazzInvite 
      |                 WHERE ciPersonUid = CAST(? AS BIGINT) AND ciClazzUid = CAST(? AS BIGINT) 
      |              AND inviteExpire > CAST(? AS BIGINT) AND inviteStatus = 0) AS _PagingData LIMIT ? OFFSET ?
      """.trimMargin(),
      postgreSql = """
      |SELECT * FROM (SELECT * FROM ClazzInvite 
      |                 WHERE ciPersonUid = ? AND ciClazzUid = ? 
      |              AND inviteExpire > ? AND inviteStatus = 0) AS _PagingData LIMIT ? OFFSET ?
      |""".trimMargin(),
      readOnly = true,)
    ) { _stmt -> 
      _stmt.setLong(1,ciPersonUid)
      _stmt.setLong(2,clazzUid)
      _stmt.setLong(3,currentTime)
      _stmt.setInt(4,_limit)
      _stmt.setInt(5,_offset)
      _stmt.executeQueryAsyncKmp().useResults{ _result -> 
        _result.mapRows {
          val _tmp_ciUid = _result.getLong("ciUid")
          val _tmp_ciPersonUid = _result.getLong("ciPersonUid")
          val _tmp_ciRoleId = _result.getLong("ciRoleId")
          val _tmp_ciClazzUid = _result.getLong("ciClazzUid")
          val _tmp_inviteType = _result.getInt("inviteType")
          val _tmp_inviteContact = _result.getStringNonNull("inviteContact")
          val _tmp_inviteToken = _result.getStringNonNull("inviteToken")
          val _tmp_inviteStatus = _result.getInt("inviteStatus")
          val _tmp_inviteExpire = _result.getLong("inviteExpire")
          val _tmp_inviteLct = _result.getLong("inviteLct")
          ClazzInvite().apply {
            this.ciUid = _tmp_ciUid
            this.ciPersonUid = _tmp_ciPersonUid
            this.ciRoleId = _tmp_ciRoleId
            this.ciClazzUid = _tmp_ciClazzUid
            this.inviteType = _tmp_inviteType
            this.inviteContact = _tmp_inviteContact
            this.inviteToken = _tmp_inviteToken
            this.inviteStatus = _tmp_inviteStatus
            this.inviteExpire = _tmp_inviteExpire
            this.inviteLct = _tmp_inviteLct
          }
        }
      }
    }

    override suspend fun countRows(): Int = _db.prepareAndUseStatementAsync(PreparedStatementConfig(
      sql = """
      |SELECT COUNT(*) FROM (SELECT * FROM ClazzInvite 
      |                 WHERE ciPersonUid = CAST(? AS BIGINT) AND ciClazzUid = CAST(? AS BIGINT) 
      |              AND inviteExpire > CAST(? AS BIGINT) AND inviteStatus = 0) AS _PagingCount
      """.trimMargin(),
      postgreSql = """
      |SELECT COUNT(*) FROM (SELECT * FROM ClazzInvite 
      |                 WHERE ciPersonUid = ? AND ciClazzUid = ? 
      |              AND inviteExpire > ? AND inviteStatus = 0) AS _PagingCount
      |""".trimMargin(),
      readOnly = true,)
    ) { _stmt -> 
      _stmt.setLong(1,ciPersonUid)
      _stmt.setLong(2,clazzUid)
      _stmt.setLong(3,currentTime)
      _stmt.executeQueryAsyncKmp().useResults{ _result -> 
        _result.mapNextRow(0) {
          _result.getInt(1)
        }
      }
    }
  }

  override suspend fun updateClazzInviteToRevokeInvite(inviteContact: String): Int =
      _db.prepareAndUseStatementAsync(PreparedStatementConfig(
    sql = """
    |
    |        UPDATE ClazzInvite 
    |          SET inviteStatus = 3
    |        WHERE inviteContact = ?
    """.trimMargin(),
    readOnly = false,)
  ) { _stmt -> 
    _stmt.setString(1,inviteContact)
    _stmt.executeUpdateAsyncKmp()
  }

  override suspend fun findClazzInviteFromContact(inviteContact: String): ClazzInvite? =
      _db.prepareAndUseStatementAsync(PreparedStatementConfig(
    sql = "SELECT * FROM ClazzInvite WHERE inviteContact = ?",
    readOnly = true,)
  ) { _stmt -> 
    _stmt.setString(1,inviteContact)
    _stmt.executeQueryAsyncKmp().useResults{ _result -> 
      _result.mapNextRow(null) {
        val _tmp_ciUid = _result.getLong("ciUid")
        val _tmp_ciPersonUid = _result.getLong("ciPersonUid")
        val _tmp_ciRoleId = _result.getLong("ciRoleId")
        val _tmp_ciClazzUid = _result.getLong("ciClazzUid")
        val _tmp_inviteType = _result.getInt("inviteType")
        val _tmp_inviteContact = _result.getStringNonNull("inviteContact")
        val _tmp_inviteToken = _result.getStringNonNull("inviteToken")
        val _tmp_inviteStatus = _result.getInt("inviteStatus")
        val _tmp_inviteExpire = _result.getLong("inviteExpire")
        val _tmp_inviteLct = _result.getLong("inviteLct")
        ClazzInvite().apply {
          this.ciUid = _tmp_ciUid
          this.ciPersonUid = _tmp_ciPersonUid
          this.ciRoleId = _tmp_ciRoleId
          this.ciClazzUid = _tmp_ciClazzUid
          this.inviteType = _tmp_inviteType
          this.inviteContact = _tmp_inviteContact
          this.inviteToken = _tmp_inviteToken
          this.inviteStatus = _tmp_inviteStatus
          this.inviteExpire = _tmp_inviteExpire
          this.inviteLct = _tmp_inviteLct
        }
      }
    }
  }
}
