package com.ustadmobile.core.db.dao.xapi

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.executeUpdateAsyncKmp
import com.ustadmobile.door.room.RoomDatabase
import com.ustadmobile.lib.db.entities.xapi.GroupMemberActorJoin
import kotlin.Boolean
import kotlin.IllegalArgumentException
import kotlin.Long
import kotlin.String
import kotlin.collections.List

public class GroupMemberActorJoinDao_JdbcImpl(
  public val _db: RoomDatabase,
) : GroupMemberActorJoinDao() {
  public val _insertAdapterGroupMemberActorJoin_ignore: EntityInsertionAdapter<GroupMemberActorJoin>
      = object : EntityInsertionAdapter<GroupMemberActorJoin>(_db) {
    override fun makeSql(returnsId: Boolean): String = when(dbType) {
      DoorDbType.SQLITE -> {
        "INSERT  OR IGNORE INTO GroupMemberActorJoin (gmajGroupActorUid, gmajMemberActorUid, gmajLastMod) VALUES(?, ?, ?)"
      }
      DoorDbType.POSTGRES ->  {
        "INSERT INTO GroupMemberActorJoin (gmajGroupActorUid, gmajMemberActorUid, gmajLastMod) VALUES(?, ?, ?) ON CONFLICT (gmajGroupActorUid, gmajMemberActorUid) DO NOTHING" + if(returnsId) { " RETURNING gmajGroupActorUid" } else "" 
      }
      else -> {
        throw IllegalArgumentException("Unsupported db type")
      }
    }

    override fun bindPreparedStmtToEntity(stmt: PreparedStatement, entity: GroupMemberActorJoin) {
      stmt.setLong(1, entity.gmajGroupActorUid)
      stmt.setLong(2, entity.gmajMemberActorUid)
      stmt.setLong(3, entity.gmajLastMod)
    }
  }

  public val _insertAdapterGroupMemberActorJoin_upsert: EntityInsertionAdapter<GroupMemberActorJoin>
      = object : EntityInsertionAdapter<GroupMemberActorJoin>(_db) {
    override fun makeSql(returnsId: Boolean): String = when(dbType) {
      DoorDbType.SQLITE -> {
        "INSERT OR REPLACE INTO GroupMemberActorJoin (gmajGroupActorUid, gmajMemberActorUid, gmajLastMod) VALUES(?, ?, ?)"
      }
      DoorDbType.POSTGRES ->  {
        "INSERT INTO GroupMemberActorJoin (gmajGroupActorUid, gmajMemberActorUid, gmajLastMod) VALUES(?, ?, ?) ON CONFLICT (gmajGroupActorUid, gmajMemberActorUid) DO UPDATE SET gmajLastMod = excluded.gmajLastMod" + if(returnsId) { " RETURNING gmajGroupActorUid" } else "" 
      }
      else -> {
        throw IllegalArgumentException("Unsupported db type")
      }
    }

    override fun bindPreparedStmtToEntity(stmt: PreparedStatement, entity: GroupMemberActorJoin) {
      stmt.setLong(1, entity.gmajGroupActorUid)
      stmt.setLong(2, entity.gmajMemberActorUid)
      stmt.setLong(3, entity.gmajLastMod)
    }
  }

  override suspend fun insertOrIgnoreListAsync(entities: List<GroupMemberActorJoin>) {
    _insertAdapterGroupMemberActorJoin_ignore.insertListAsync(entities)
  }

  override suspend fun upsertListAsync(entities: List<GroupMemberActorJoin>) {
    _insertAdapterGroupMemberActorJoin_upsert.insertListAsync(entities)
  }

  override suspend fun updateLastModifiedTimeIfNeededAsync(
    gmajGroupActorUid: Long,
    gmajMemberActorUid: Long,
    lastModTime: Long,
  ) {
    _db.prepareAndUseStatementAsync(PreparedStatementConfig(
      sql = """
      |
      |        UPDATE GroupMemberActorJoin
      |           SET gmajLastMod = ?
      |         WHERE gmajGroupActorUid = ?
      |           AND gmajMemberActorUid = ?
      |           AND gmajLastMod != ? 
      |    
      """.trimMargin(),
      readOnly = false,)
    ) { _stmt -> 
      _stmt.setLong(1,lastModTime)
      _stmt.setLong(2,gmajGroupActorUid)
      _stmt.setLong(3,gmajMemberActorUid)
      _stmt.setLong(4,lastModTime)
      _stmt.executeUpdateAsyncKmp()
    }
  }
}
