package com.ustadmobile.core.db.dao

import com.ustadmobile.door.DoorDbType
import com.ustadmobile.door.EntityInsertionAdapter
import com.ustadmobile.door.PreparedStatementConfig
import com.ustadmobile.door.ext.prepareAndUseStatementAsync
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.mapRows
import com.ustadmobile.door.jdbc.ext.useResults
import com.ustadmobile.door.room.RoomDatabase
import com.ustadmobile.lib.db.entities.TransferJobError
import kotlin.Boolean
import kotlin.IllegalArgumentException
import kotlin.Int
import kotlin.String
import kotlin.collections.List

public class TransferJobErrorDao_JdbcImpl(
  public val _db: RoomDatabase,
) : TransferJobErrorDao() {
  public val _insertAdapterTransferJobError_abort: EntityInsertionAdapter<TransferJobError> = object
      : EntityInsertionAdapter<TransferJobError>(_db) {
    override fun makeSql(returnsId: Boolean): String = when(dbType) {
      DoorDbType.SQLITE -> {
        "INSERT INTO TransferJobError (tjeId, tjeTjUid, tjeTime, tjeErrorStr, tjeDismissed) VALUES(?, ?, ?, ?, ?)"
      }
      DoorDbType.POSTGRES ->  {
        "INSERT INTO TransferJobError (tjeId, tjeTjUid, tjeTime, tjeErrorStr, tjeDismissed) VALUES(COALESCE(?,nextval('TransferJobError_tjeId_seq')), ?, ?, ?, ?)" + if(returnsId) { " RETURNING tjeId" } else "" 
      }
      else -> {
        throw IllegalArgumentException("Unsupported db type")
      }
    }

    override fun bindPreparedStmtToEntity(stmt: PreparedStatement, entity: TransferJobError) {
      if(entity.tjeId == 0) {
        stmt.setObject(1, null)
      } else {
        stmt.setInt(1, entity.tjeId)
      }
      stmt.setInt(2, entity.tjeTjUid)
      stmt.setLong(3, entity.tjeTime)
      stmt.setString(4, entity.tjeErrorStr)
      stmt.setBoolean(5, entity.tjeDismissed)
    }
  }

  override suspend fun insertAsync(error: TransferJobError) {
    _insertAdapterTransferJobError_abort.insertAsync(error)
  }

  override suspend fun findByJobId(jobUid: Int): List<TransferJobError> =
      _db.prepareAndUseStatementAsync(PreparedStatementConfig(
    sql = """
    |
    |        SELECT TransferJobError.*
    |          FROM TransferJobError
    |         WHERE TransferJobError.tjeTjUid = ?
    |    
    """.trimMargin(),
    readOnly = true,)
  ) { _stmt -> 
    _stmt.setInt(1,jobUid)
    _stmt.executeQueryAsyncKmp().useResults{ _result -> 
      _result.mapRows {
        val _tmp_tjeId = _result.getInt("tjeId")
        val _tmp_tjeTjUid = _result.getInt("tjeTjUid")
        val _tmp_tjeTime = _result.getLong("tjeTime")
        val _tmp_tjeErrorStr = _result.getString("tjeErrorStr")
        val _tmp_tjeDismissed = _result.getBoolean("tjeDismissed")
        TransferJobError().apply {
          this.tjeId = _tmp_tjeId
          this.tjeTjUid = _tmp_tjeTjUid
          this.tjeTime = _tmp_tjeTime
          this.tjeErrorStr = _tmp_tjeErrorStr
          this.tjeDismissed = _tmp_tjeDismissed
        }
      }
    }
  }

  override suspend fun dismissErrorByJobId(jobUid: Int, dismissed: Boolean) {
    _db.prepareAndUseStatementAsync(PreparedStatementConfig(
      sql = """
      |
      |        UPDATE TransferJobError
      |           SET tjeDismissed = ?
      |         WHERE TransferJobError.tjeTjUid = ?  
      |    
      """.trimMargin(),
      readOnly = false,)
    ) { _stmt -> 
      _stmt.setBoolean(1,dismissed)
      _stmt.setInt(2,jobUid)
      _stmt.executeUpdateAsyncKmp()
    }
  }
}
