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.mapNextRow
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.ErrorReport
import kotlin.Boolean
import kotlin.IllegalArgumentException
import kotlin.Int
import kotlin.Long
import kotlin.String
import kotlin.collections.List

public class ErrorReportDao_JdbcImpl(
  public val _db: RoomDatabase,
) : ErrorReportDao() {
  public val _insertAdapterErrorReport_abort: EntityInsertionAdapter<ErrorReport> = object :
      EntityInsertionAdapter<ErrorReport>(_db) {
    override fun makeSql(returnsId: Boolean): String = when(dbType) {
      DoorDbType.SQLITE -> {
        "INSERT INTO ErrorReport (errUid, errPcsn, errLcsn, errLcb, errLct, severity, timestamp, presenterUri, appVersion, versionCode, errorCode, operatingSys, osVersion, stackTrace, message) VALUES(?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)"
      }
      DoorDbType.POSTGRES ->  {
        "INSERT INTO ErrorReport (errUid, errPcsn, errLcsn, errLcb, errLct, severity, timestamp, presenterUri, appVersion, versionCode, errorCode, operatingSys, osVersion, stackTrace, message) VALUES(COALESCE(?,nextval('ErrorReport_errUid_seq')), ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?, ?)" + if(returnsId) { " RETURNING errUid" } else "" 
      }
      else -> {
        throw IllegalArgumentException("Unsupported db type")
      }
    }

    override fun bindPreparedStmtToEntity(stmt: PreparedStatement, entity: ErrorReport) {
      if(entity.errUid == 0L) {
        stmt.setObject(1, null)
      } else {
        stmt.setLong(1, entity.errUid)
      }
      stmt.setLong(2, entity.errPcsn)
      stmt.setLong(3, entity.errLcsn)
      stmt.setInt(4, entity.errLcb)
      stmt.setLong(5, entity.errLct)
      stmt.setInt(6, entity.severity)
      stmt.setLong(7, entity.timestamp)
      stmt.setString(8, entity.presenterUri)
      stmt.setString(9, entity.appVersion)
      stmt.setInt(10, entity.versionCode)
      stmt.setInt(11, entity.errorCode)
      stmt.setString(12, entity.operatingSys)
      stmt.setString(13, entity.osVersion)
      stmt.setString(14, entity.stackTrace)
      stmt.setString(15, entity.message)
    }
  }

  override suspend fun insertAsync(errorReport: ErrorReport): Long {
    val _retVal = _insertAdapterErrorReport_abort.insertAndReturnIdAsync(errorReport)
    return _retVal
  }

  override suspend fun findByUidAsync(errUid: Long): ErrorReport? =
      _db.prepareAndUseStatementAsync(PreparedStatementConfig(
    sql = """
    |
    |        SELECT ErrorReport.* 
    |          FROM ErrorReport
    |         WHERE errUid = ?
    |    
    """.trimMargin(),
    readOnly = true,)
  ) { _stmt -> 
    _stmt.setLong(1,errUid)
    _stmt.executeQueryAsyncKmp().useResults{ _result -> 
      _result.mapNextRow(null) {
        val _tmp_errUid = _result.getLong("errUid")
        val _tmp_errPcsn = _result.getLong("errPcsn")
        val _tmp_errLcsn = _result.getLong("errLcsn")
        val _tmp_errLcb = _result.getInt("errLcb")
        val _tmp_errLct = _result.getLong("errLct")
        val _tmp_severity = _result.getInt("severity")
        val _tmp_timestamp = _result.getLong("timestamp")
        val _tmp_presenterUri = _result.getString("presenterUri")
        val _tmp_appVersion = _result.getString("appVersion")
        val _tmp_versionCode = _result.getInt("versionCode")
        val _tmp_errorCode = _result.getInt("errorCode")
        val _tmp_operatingSys = _result.getString("operatingSys")
        val _tmp_osVersion = _result.getString("osVersion")
        val _tmp_stackTrace = _result.getString("stackTrace")
        val _tmp_message = _result.getString("message")
        ErrorReport().apply {
          this.errUid = _tmp_errUid
          this.errPcsn = _tmp_errPcsn
          this.errLcsn = _tmp_errLcsn
          this.errLcb = _tmp_errLcb
          this.errLct = _tmp_errLct
          this.severity = _tmp_severity
          this.timestamp = _tmp_timestamp
          this.presenterUri = _tmp_presenterUri
          this.appVersion = _tmp_appVersion
          this.versionCode = _tmp_versionCode
          this.errorCode = _tmp_errorCode
          this.operatingSys = _tmp_operatingSys
          this.osVersion = _tmp_osVersion
          this.stackTrace = _tmp_stackTrace
          this.message = _tmp_message
        }
      }
    }
  }

  override suspend fun findByErrorCode(errCode: Int): List<ErrorReport> =
      _db.prepareAndUseStatementAsync(PreparedStatementConfig(
    sql = """
    |
    |        SELECT ErrorReport.*
    |          FROM ErrorReport
    |         WHERE errorCode = ?  
    |    
    """.trimMargin(),
    readOnly = true,)
  ) { _stmt -> 
    _stmt.setInt(1,errCode)
    _stmt.executeQueryAsyncKmp().useResults{ _result -> 
      _result.mapRows {
        val _tmp_errUid = _result.getLong("errUid")
        val _tmp_errPcsn = _result.getLong("errPcsn")
        val _tmp_errLcsn = _result.getLong("errLcsn")
        val _tmp_errLcb = _result.getInt("errLcb")
        val _tmp_errLct = _result.getLong("errLct")
        val _tmp_severity = _result.getInt("severity")
        val _tmp_timestamp = _result.getLong("timestamp")
        val _tmp_presenterUri = _result.getString("presenterUri")
        val _tmp_appVersion = _result.getString("appVersion")
        val _tmp_versionCode = _result.getInt("versionCode")
        val _tmp_errorCode = _result.getInt("errorCode")
        val _tmp_operatingSys = _result.getString("operatingSys")
        val _tmp_osVersion = _result.getString("osVersion")
        val _tmp_stackTrace = _result.getString("stackTrace")
        val _tmp_message = _result.getString("message")
        ErrorReport().apply {
          this.errUid = _tmp_errUid
          this.errPcsn = _tmp_errPcsn
          this.errLcsn = _tmp_errLcsn
          this.errLcb = _tmp_errLcb
          this.errLct = _tmp_errLct
          this.severity = _tmp_severity
          this.timestamp = _tmp_timestamp
          this.presenterUri = _tmp_presenterUri
          this.appVersion = _tmp_appVersion
          this.versionCode = _tmp_versionCode
          this.errorCode = _tmp_errorCode
          this.operatingSys = _tmp_operatingSys
          this.osVersion = _tmp_osVersion
          this.stackTrace = _tmp_stackTrace
          this.message = _tmp_message
        }
      }
    }
  }
}
