package com.ustadmobile.core.db.dao

import androidx.room.Dao
import androidx.room.Insert
import androidx.room.Query
import com.ustadmobile.lib.db.entities.TransferJobItem
import kotlin.Any
import kotlin.Int
import kotlin.Long
import kotlin.collections.List
import kotlinx.coroutines.flow.Flow

@Dao
public actual abstract class TransferJobItemDao {
  @Insert(
    entity = Any::class,
    onConflict = 3,
  )
  public actual abstract suspend fun insertList(items: List<TransferJobItem>)

  @Insert(
    entity = Any::class,
    onConflict = 3,
  )
  public actual abstract suspend fun insert(item: TransferJobItem): Long

  @Query(`value` =
      "\n        SELECT TransferJobItem.*\n          FROM TransferJobItem\n         WHERE TransferJobItem.tjiTjUid = :jobUid\n    ")
  public actual abstract suspend fun findByJobUid(jobUid: Int): List<TransferJobItem>

  @Query(`value` =
      "\n        SELECT TransferJobItem.*\n          FROM TransferJobItem\n         WHERE TransferJobItem.tjiTjUid = :jobUid\n           AND TransferJobItem.tjiStatus < 21\n    ")
  public actual abstract suspend fun findPendingByJobUid(jobUid: Int): List<TransferJobItem>

  @Query(`value` =
      "\n        UPDATE TransferJobItem\n           SET tjTransferred = :transferred\n         WHERE tjiUid = :jobItemUid\n    ")
  public actual abstract suspend fun updateTransferredProgress(jobItemUid: Int, transferred: Long)

  @Query(`value` =
      "\n        UPDATE TransferJobItem\n           SET tjiStatus = :status\n         WHERE tjiUid = :jobItemUid  \n    ")
  public actual abstract suspend fun updateStatus(jobItemUid: Int, status: Int)

  @Query(`value` =
      "\n        INSERT INTO OutgoingReplication(destNodeId, orTableId, orPk1, orPk2)\n        SELECT :destNodeId AS destNodeId, \n              TransferJobItem.tjiTableId AS orTableId,\n              TransferJobItem.tjiEntityUid AS orPk1,\n              0 AS orPk2\n        FROM TransferJobItem\n       WHERE TransferJobItem.tjiUid = :transferJobItemUid\n         AND TransferJobItem.tjiTableId != 0\n         AND TransferJobItem.tjiStatus = 21\n         AND NOT EXISTS(\n             SELECT OtherJob.tjiUid\n               FROM TransferJobItem OtherJob\n              WHERE OtherJob.tjiTableId = TransferJobItem.tjiTableId\n                AND OtherJob.tjiEntityUid = TransferJobItem.tjiEntityUid\n                AND OtherJob.tjiEntityEtag = TransferJobItem.tjiEntityEtag\n                AND OtherJob.tjiStatus != 21)\n    ")
  public actual abstract suspend
      fun insertOutgoingReplicationForTransferJobItemIfDone(destNodeId: Long,
      transferJobItemUid: Int)

  @Query(`value` =
      "\n        UPDATE TransferJobItem\n           SET tjiStatus = :status\n         WHERE tjiTjUid = :jobUid\n           AND tjiStatus != 21 \n    ")
  public actual abstract suspend fun updateStatusIfNotCompleteForAllInJob(jobUid: Int, status: Int)

  @Query(`value` =
      "\n       SELECT COUNT(*)\n         FROM TransferJobItem\n        WHERE TransferJobItem.tjiTjUid = :jobUid\n          AND TransferjobItem.tjiStatus != 21\n    ")
  public actual abstract suspend fun findNumberJobItemsNotComplete(jobUid: Int): Int

  @Query(`value` =
      "\n        SELECT TransferJobItem.*\n          FROM TransferJobItem\n         WHERE TransferJobItem.tjiTableId = :tableId\n           AND TransferJobItem.tjiEntityUid IN (:entityUidList)\n    ")
  public actual abstract fun findByEntityUidList(entityUidList: List<Long>, tableId: Int):
      Flow<List<TransferJobItem>>
}
