package com.ustadmobile.core.db.dao

import androidx.paging.PagingSource
import androidx.room.Dao
import androidx.room.Insert
import androidx.room.Query
import androidx.room.Update
import com.ustadmobile.lib.db.entities.Schedule
import kotlin.Any
import kotlin.Boolean
import kotlin.Int
import kotlin.Long
import kotlin.collections.List
import kotlinx.coroutines.flow.Flow

@Dao
public actual abstract class ScheduleDao : BaseDao<Schedule> {
  @Insert(
    entity = Any::class,
    onConflict = 3,
  )
  actual abstract override fun insert(entity: Schedule): Long

  @Update(
    entity = Any::class,
    onConflict = 3,
  )
  public actual abstract suspend fun updateAsync(entity: Schedule): Int

  @Insert(
    onConflict = 1,
    entity = Any::class,
  )
  public actual abstract suspend fun upsertListAsync(entities: List<Schedule>)

  @Query(`value` =
      "\n        UPDATE Schedule \n           SET scheduleActive = :active,\n               scheduleLastChangedTime = :changeTime\n         WHERE scheduleUid = :scheduleUid\n            ")
  public actual abstract suspend fun updateScheduleActivated(
    scheduleUid: Long,
    active: Boolean,
    changeTime: Long,
  )

  @Query(`value` = "SELECT * FROM Schedule WHERE scheduleUid = :uid")
  public actual abstract fun findByUid(uid: Long): Schedule?

  @Query(`value` = "SELECT * FROM Schedule WHERE scheduleUid = :uid")
  public actual abstract suspend fun findByUidAsync(uid: Long): Schedule?

  @Query(`value` =
      "SELECT * FROM Schedule WHERE scheduleClazzUid = :clazzUid AND CAST(scheduleActive AS INTEGER) = 1 ")
  public actual abstract fun findAllSchedulesByClazzUid(clazzUid: Long): PagingSource<Int, Schedule>

  @Query(`value` =
      "SELECT * FROM Schedule WHERE scheduleClazzUid = :clazzUid AND CAST(scheduleActive AS INTEGER) = 1")
  public actual abstract fun findAllSchedulesByClazzUidAsList(clazzUid: Long): List<Schedule>

  @Query(`value` =
      "SELECT * FROM Schedule WHERE scheduleClazzUid = :clazzUid AND CAST(scheduleActive AS INTEGER) = 1")
  public actual abstract fun findAllSchedulesByClazzUidAsLiveList(clazzUid: Long):
      Flow<List<Schedule>>

  @Query(`value` =
      "SELECT * FROM Schedule WHERE scheduleClazzUid = :clazzUid AND CAST(scheduleActive AS INTEGER) = 1 ")
  public actual abstract suspend fun findAllSchedulesByClazzUidAsync(clazzUid: Long): List<Schedule>
}
