package com.ustadmobile.core.db.dao

import androidx.paging.PagingSource
import androidx.room.Dao
import androidx.room.Insert
import androidx.room.Query
import com.ustadmobile.lib.db.composites.EnrolmentRequestAndCoursePic
import com.ustadmobile.lib.db.composites.EnrolmentRequestAndPersonDetails
import com.ustadmobile.lib.db.entities.EnrolmentRequest
import kotlin.Any
import kotlin.Boolean
import kotlin.Int
import kotlin.Long
import kotlin.String
import kotlin.collections.List
import kotlinx.coroutines.flow.Flow

@Dao
public actual abstract class EnrolmentRequestDao {
  @Insert(
    entity = Any::class,
    onConflict = 3,
  )
  public actual abstract suspend fun insert(enrolmentRequest: EnrolmentRequest)

  @Query(`value` =
      "\n        SELECT EnrolmentRequest.*\n          FROM EnrolmentRequest\n         WHERE EnrolmentRequest.erPersonUid = :personUid\n           AND EnrolmentRequest.erClazzUid = :clazzUid\n           AND (:statusFilter = 0 OR EnrolmentRequest.erStatus = :statusFilter)\n    ")
  public actual abstract suspend fun findByClazzAndPerson(
    personUid: Long,
    clazzUid: Long,
    statusFilter: Int,
  ): List<EnrolmentRequest>

  @Query(`value` =
      "\n        SELECT EXISTS(\n               SELECT EnrolmentRequest.erUid\n                 FROM EnrolmentRequest\n                WHERE EnrolmentRequest.erPersonUid = :personUid\n                  AND EnrolmentRequest.erClazzUid = :clazzUid\n                  AND EnrolmentRequest.erStatus = 1)\n    ")
  public actual abstract suspend fun hasPendingRequests(personUid: Long, clazzUid: Long): Boolean

  @Query(`value` =
      "\n        SELECT EnrolmentRequest.*, CoursePicture.*\n          FROM EnrolmentRequest\n               LEFT JOIN CoursePicture\n                         ON CoursePicture.coursePictureUid = EnrolmentRequest.erClazzUid\n         WHERE EnrolmentRequest.erPersonUid = :accountPersonUid \n           AND (:statusFilter = 0 OR EnrolmentRequest.erStatus = :statusFilter)\n    ")
  public actual abstract fun findRequestsForUserAsFlow(accountPersonUid: Long, statusFilter: Int):
      Flow<List<EnrolmentRequestAndCoursePic>>

  @Query(`value` =
      "\n        UPDATE EnrolmentRequest\n           SET erStatus = :status,\n               erLastModified = :updateTime\n         WHERE erUid = :uid      \n    ")
  public actual abstract suspend fun updateStatus(
    uid: Long,
    status: Int,
    updateTime: Long,
  )

  @Query(`value` =
      "\n        SELECT EnrolmentRequest.*, PersonPicture.*, Person.*\n          FROM EnrolmentRequest\n               JOIN Person\n                    ON Person.personUid = EnrolmentRequest.erPersonUid\n               LEFT JOIN PersonPicture\n                         ON PersonPicture.personPictureUid = EnrolmentRequest.erPersonUid\n         WHERE EnrolmentRequest.erClazzUid = :clazzUid\n           AND (:statusFilter = 0 OR EnrolmentRequest.erStatus = :statusFilter)\n           AND (CAST(:includeDeleted AS INTEGER) = 1 OR NOT EnrolmentRequest.erDeleted)\n           AND (:searchText = '%' OR EnrolmentRequest.erPersonFullname LIKE :searchText)\n      ORDER BY CASE(:sortOrder)\n                WHEN 1 THEN EnrolmentRequest.erPersonFullname\n                WHEN 3 THEN EnrolmentRequest.erPersonFullname\n                ELSE ''\n                END ASC,\n                CASE(:sortOrder)\n                WHEN 2 THEN EnrolmentRequest.erPersonFullname\n                WHEN 4 THEN EnrolmentRequest.erPersonFullname\n                ELSE ''\n            END DESC,\n            CASE(:sortOrder)\n                WHEN 7 THEN EnrolmentRequest.erRequestTime\n                ELSE 0\n            END ASC,\n            CASE(:sortOrder)\n                WHEN 8 THEN EnrolmentRequest.erRequestTime\n                ELSE 0\n            END DESC     \n    ")
  public actual abstract fun findPendingEnrolmentsForCourse(
    clazzUid: Long,
    includeDeleted: Boolean,
    statusFilter: Int,
    searchText: String,
    sortOrder: Int,
  ): PagingSource<Int, EnrolmentRequestAndPersonDetails>
}
