package com.ustadmobile.core.db.dao

import androidx.paging.PagingSource
import com.ustadmobile.lib.db.composites.ClazzEnrolmentAndPerson
import com.ustadmobile.lib.db.composites.ClazzEnrolmentAndPersonDetailDetails
import com.ustadmobile.lib.db.composites.CourseNameAndPersonName
import com.ustadmobile.lib.db.composites.PersonAndClazzMemberListDetails
import com.ustadmobile.lib.db.entities.ClazzEnrolment
import com.ustadmobile.lib.db.entities.ClazzEnrolmentWithClazz
import com.ustadmobile.lib.db.entities.ClazzEnrolmentWithLeavingReason
import com.ustadmobile.lib.db.entities.ClazzEnrolmentWithPerson
import com.ustadmobile.lib.db.entities.xapi.ActorEntity
import kotlin.Boolean
import kotlin.Int
import kotlin.Long
import kotlin.String
import kotlin.collections.List
import kotlinx.coroutines.flow.Flow

public actual abstract class ClazzEnrolmentDao : BaseDao<ClazzEnrolment> {
  public actual abstract fun insertListAsync(entityList: List<ClazzEnrolment>)

  public actual abstract fun findAllEnrolmentsByPersonAndClazzUid(personUid: Long, clazzUid: Long):
      Flow<List<ClazzEnrolmentWithLeavingReason>>

  public actual abstract suspend fun findEnrolmentWithLeavingReason(enrolmentUid: Long):
      ClazzEnrolmentWithLeavingReason?

  public actual abstract suspend fun updateDateLeftByUid(
    clazzEnrolmentUid: Long,
    endDate: Long,
    updateTime: Long,
  )

  public actual abstract suspend fun updateAsync(entity: ClazzEnrolment): Int

  public actual abstract fun findAllClazzesByPersonWithClazz(accountPersonUid: Long,
      otherPersonUid: Long): Flow<List<ClazzEnrolmentAndPersonDetailDetails>>

  public actual abstract fun findAllByPersonUid(personUid: Long): Flow<List<ClazzEnrolment>>

  public actual abstract suspend fun findAllClazzesByPersonWithClazzAsListAsync(personUid: Long):
      List<ClazzEnrolmentWithClazz>

  public actual abstract suspend fun getAllClazzEnrolledAtTimeAsync(
    clazzUid: Long,
    date: Long,
    roleFilter: Int,
    personUidFilter: Long,
  ): List<ClazzEnrolmentWithPerson>

  public actual abstract suspend fun getAllEnrolmentsAtTimeByClazzAndPerson(
    clazzUid: Long,
    accountPersonUid: Long,
    time: Long,
  ): List<ClazzEnrolment>

  public actual abstract suspend fun findByUid(uid: Long): ClazzEnrolment?

  public actual abstract fun findByUidLive(uid: Long): Flow<ClazzEnrolment?>

  public actual abstract fun findByClazzUidAndRole(
    clazzUid: Long,
    roleId: Int,
    sortOrder: Int,
    searchText: String?,
    filter: Int,
    accountPersonUid: Long,
    currentTime: Long,
    permission: Long,
  ): PagingSource<Int, PersonAndClazzMemberListDetails>

  public actual abstract fun findByClazzUidAndRoleForGradebook(
    clazzUid: Long,
    roleId: Int,
    sortOrder: Int,
    searchText: String?,
    filter: Int,
    accountPersonUid: Long,
    currentTime: Long,
  ): PagingSource<Int, PersonAndClazzMemberListDetails>

  public actual abstract suspend fun findActorEntitiesForGradebook(
    clazzUid: Long,
    roleId: Int,
    sortOrder: Int,
    searchText: String?,
    filter: Int,
    accountPersonUid: Long,
    currentTime: Long,
    studentsLimit: Int,
    studentsOffset: Int,
  ): List<ActorEntity>

  public actual abstract suspend
      fun findEnrolmentsAndPersonByClazzUidWithPermissionCheck(clazzUid: Long,
      accountPersonUid: Long): List<ClazzEnrolmentAndPerson>

  public actual abstract suspend fun findByAccountPersonUidAndClazzUid(accountPersonUid: Long,
      clazzUid: Long): List<ClazzEnrolment>

  public actual abstract suspend fun findEnrolmentsByClazzUidAndRole(
    clazzUid: Long,
    accountPersonUid: Long,
    roleId: Int,
    permission: Long,
  ): List<ClazzEnrolment>

  public actual abstract suspend fun findEnrolmentsByClazzUidAndRolePaged(
    clazzUid: Long,
    roleId: Int,
    sortOrder: Int,
    searchText: String?,
    filter: Int,
    accountPersonUid: Long,
    currentTime: Long,
    permission: Long,
    studentsLimit: Int,
    studentsOffset: Int,
  ): List<ClazzEnrolment>

  public actual abstract suspend fun findAllEnrolmentsByClazzUidAndRole(clazzUid: Long,
      roleId: Int): List<ClazzEnrolment>

  public actual abstract fun updateClazzEnrolmentActiveForClazzEnrolment(
    clazzEnrolmentUid: Long,
    enrolled: Boolean,
    timeChanged: Long,
  ): Int

  public actual abstract suspend fun updateClazzEnrolmentRole(
    personUid: Long,
    clazzUid: Long,
    newRole: Int,
    oldRole: Int,
    updateTime: Long,
  ): Int

  public actual abstract suspend fun getClazzNameAndPersonName(personUid: Long, clazzUid: Long):
      CourseNameAndPersonName?

  public actual abstract suspend
      fun findClazzEnrolmentEntitiesForPersonViewPermissionCheck(accountPersonUid: Long,
      otherPersonUid: Long): List<ClazzEnrolment>
}
