package com.ustadmobile.core.db.dao

import androidx.room.Dao
import androidx.room.Insert
import androidx.room.Query
import androidx.room.Update
import com.ustadmobile.lib.db.entities.ClazzLogAttendanceRecord
import com.ustadmobile.lib.db.entities.ClazzLogAttendanceRecordWithPerson
import kotlin.Long
import kotlin.Unit
import kotlin.collections.List

@Dao
public actual abstract class ClazzLogAttendanceRecordDao : BaseDao<ClazzLogAttendanceRecord> {
  @Query(`value` =
      "\n     REPLACE INTO ClazzLogAttendanceRecordReplicate(clarPk, clarDestination)\n      SELECT DISTINCT ClazzLogAttendanceRecord.clazzLogAttendanceRecordUid AS clarUid,\n             :newNodeId AS clarDestination\n        FROM UserSession\n             JOIN PersonGroupMember \n                  ON UserSession.usPersonUid = PersonGroupMember.groupMemberPersonUid\n             \n               JOIN ScopedGrant\n                    ON ScopedGrant.sgGroupUid = PersonGroupMember.groupMemberGroupUid\n                        AND (ScopedGrant.sgPermissions & \n        \n                  2048 \n                  \n                       ) > 0\n               JOIN Clazz \n                    ON \n            ((ScopedGrant.sgTableId = -2\n                                AND ScopedGrant.sgEntityUid = -2)\n                            OR (ScopedGrant.sgTableId = 6\n                                AND ScopedGrant.sgEntityUid = Clazz.clazzUid)\n                            OR (ScopedGrant.sgTableId = 164\n                                AND ScopedGrant.sgEntityUid = Clazz.clazzSchoolUid))\n        \n        \n             JOIN ClazzLog\n                  ON ClazzLog.clazzLogClazzUid = Clazz.clazzUid\n             JOIN ClazzLogAttendanceRecord \n                  ON ClazzLogAttendanceRecord.clazzLogAttendanceRecordClazzLogUid = ClazzLog.clazzLogUid\n       WHERE ClazzLogAttendanceRecord.clazzLogAttendanceRecordLastChangedTime != COALESCE(\n             (SELECT clarVersionId\n                FROM ClazzLogAttendanceRecordReplicate\n               WHERE clarPk = ClazzLogAttendanceRecord.clazzLogAttendanceRecordUid\n                 AND clarDestination = :newNodeId), 0) \n      /*psql ON CONFLICT(clarPk, clarDestination) DO UPDATE\n             SET clarPending = true\n      */       \n    ")
  public actual abstract suspend fun replicateOnNewNode(newNodeId: Long): Unit

  @Query(`value` =
      "\n REPLACE INTO ClazzLogAttendanceRecordReplicate(clarPk, clarDestination)\n  SELECT DISTINCT ClazzLogAttendanceRecord.clazzLogAttendanceRecordUid AS clarUid,\n         UserSession.usClientNodeId AS clarDestination\n    FROM ChangeLog\n         JOIN ClazzLogAttendanceRecord \n              ON ChangeLog.chTableId = 15 \n             AND ClazzLogAttendanceRecord.clazzLogAttendanceRecordUid = ChangeLog.chEntityPk\n         JOIN ClazzLog\n              ON ClazzLog.clazzLogUid = ClazzLogAttendanceRecord.clazzLogAttendanceRecordClazzLogUid\n         JOIN Clazz \n              ON Clazz.clazzUid = ClazzLog.clazzLogClazzUid \n         \n            JOIN ScopedGrant\n                 ON \n            ((ScopedGrant.sgTableId = -2\n                                AND ScopedGrant.sgEntityUid = -2)\n                            OR (ScopedGrant.sgTableId = 6\n                                AND ScopedGrant.sgEntityUid = Clazz.clazzUid)\n                            OR (ScopedGrant.sgTableId = 164\n                                AND ScopedGrant.sgEntityUid = Clazz.clazzSchoolUid))\n        \n                    AND (ScopedGrant.sgPermissions & \n        \n              2\n              \n              \n                                                       ) > 0\n             JOIN PersonGroupMember AS PrsGrpMbr\n                   ON ScopedGrant.sgGroupUid = PrsGrpMbr.groupMemberGroupUid\n                                               \n              JOIN UserSession\n                   ON UserSession.usPersonUid = PrsGrpMbr.groupMemberPersonUid\n                      AND UserSession.usStatus = 1\n        \n   WHERE UserSession.usClientNodeId != (\n         SELECT nodeClientId \n           FROM SyncNode\n          LIMIT 1)\n     AND ClazzLogAttendanceRecord.clazzLogAttendanceRecordLastChangedTime != COALESCE(\n             (SELECT clarVersionId\n                FROM ClazzLogAttendanceRecordReplicate\n               WHERE clarPk = ClazzLogAttendanceRecord.clazzLogAttendanceRecordUid\n                 AND clarDestination = UserSession.usClientNodeId), 0) \n /*psql ON CONFLICT(clarPk, clarDestination) DO UPDATE\n     SET clarPending = true\n  */               \n    ")
  public actual abstract suspend fun replicateOnChange(): Unit

  @Insert(onConflict = 3)
  public actual abstract suspend fun insertListAsync(entities: List<ClazzLogAttendanceRecord>): Unit

  @Query(`value` =
      "SELECT * from ClazzLogAttendanceRecord WHERE clazzLogAttendanceRecordUid = :uid")
  public actual abstract fun findByUid(uid: Long): ClazzLogAttendanceRecord?

  @Update(onConflict = 3)
  public actual abstract suspend fun updateListAsync(entities: List<ClazzLogAttendanceRecord>): Unit

  @Query(`value` =
      "SELECT ClazzLogAttendanceRecord.*, Person.*\n         FROM ClazzLogAttendanceRecord \n         LEFT JOIN Person ON ClazzLogAttendanceRecord.clazzLogAttendanceRecordPersonUid = Person.personUid\n         WHERE clazzLogAttendanceRecordClazzLogUid = :clazzLogUid")
  public actual abstract suspend fun findByClazzLogUid(clazzLogUid: Long):
      List<ClazzLogAttendanceRecordWithPerson>

  @Query(`value` =
      "\n        UPDATE ClazzLogAttendanceRecord\n           SET clazzLogAttendanceRecordClazzLogUid = :newClazzLogUid,\n               clazzLogAttendanceRecordLastChangedTime = :changedTime\n        WHERE clazzLogAttendanceRecordClazzLogUid = :oldClazzLogUid\n    ")
  public actual abstract fun updateRescheduledClazzLogUids(
    oldClazzLogUid: Long,
    newClazzLogUid: Long,
    changedTime: Long,
  ): Unit
}
