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.SyncNode
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.useResults
import com.ustadmobile.door.room.RoomDatabase
import kotlin.Boolean
import kotlin.IllegalArgumentException
import kotlin.Long
import kotlin.String

public class SyncNodeDao_JdbcImpl(
  public val _db: RoomDatabase,
) : SyncNodeDao() {
  public val _insertAdapterSyncNode_upsert: EntityInsertionAdapter<SyncNode> = object :
      EntityInsertionAdapter<SyncNode>(_db) {
    override fun makeSql(returnsId: Boolean): String = when(dbType) {
      DoorDbType.SQLITE -> {
        "INSERT OR REPLACE INTO SyncNode (nodeClientId) VALUES(?)"
      }
      DoorDbType.POSTGRES ->  {
        "INSERT INTO SyncNode (nodeClientId) VALUES(?) ON CONFLICT (nodeClientId) DO UPDATE SET " + if(returnsId) { " RETURNING nodeClientId" } else "" 
      }
      else -> {
        throw IllegalArgumentException("Unsupported db type")
      }
    }

    override fun bindPreparedStmtToEntity(stmt: PreparedStatement, entity: SyncNode) {
      stmt.setLong(1, entity.nodeClientId)
    }
  }

  override fun replace(syncNode: SyncNode) {
    _insertAdapterSyncNode_upsert.insert(syncNode)
  }

  override suspend fun getLocalNodeClientId(): Long =
      _db.prepareAndUseStatementAsync(PreparedStatementConfig(
    sql = """
    |
    |        SELECT COALESCE(
    |               (SELECT nodeClientId 
    |                  FROM SyncNode 
    |                 LIMIT 1), 0)
    |    
    """.trimMargin(),
    readOnly = true,)
  ) { _stmt -> 
    _stmt.executeQueryAsyncKmp().useResults{ _result -> 
      _result.mapNextRow(0L) {
        _result.getLong(1)
      }
    }
  }
}
