package com.ustadmobile.core.db.dao

import androidx.lifecycle.LiveData
import androidx.paging.DataSource
import androidx.room.Dao
import androidx.room.Insert
import androidx.room.Query
import com.ustadmobile.lib.db.entities.DiscussionTopic
import com.ustadmobile.lib.db.entities.DiscussionTopicListDetail
import kotlin.Boolean
import kotlin.Int
import kotlin.Long
import kotlin.Unit
import kotlin.collections.List

@Dao
public actual abstract class DiscussionTopicDao : BaseDao<DiscussionTopic>,
    OneToManyJoinDao<DiscussionTopic> {
  @Query(`value` =
      "\n     REPLACE INTO DiscussionTopicReplicate(discussionTopicPk, discussionTopicDestination)\n      SELECT DISTINCT DiscussionTopic.discussionTopicUid AS discussionTopicPk,\n             :newNodeId AS discussionTopicDestination\n             \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                  2 \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                  \n             JOIN DiscussionTopic \n                  ON DiscussionTopic.discussionTopicClazzUid = Clazz.clazzUid\n                  \n       WHERE DiscussionTopic.discussionTopicLct != COALESCE(\n             (SELECT discussionTopicVersionId\n                FROM discussionTopicReplicate\n               WHERE discussionTopicPk = DiscussionTopic.discussionTopicUid\n                 AND discussionTopicDestination = :newNodeId), 0) \n      /*psql ON CONFLICT(discussionTopicPk, discussionTopicDestination) DO UPDATE\n             SET discussionTopicPending = true\n      */       \n    ")
  public actual abstract suspend fun replicateOnNewNode(newNodeId: Long): Unit

  @Query(`value` =
      "\n        REPLACE INTO DiscussionTopicReplicate(discussionTopicPk, discussionTopicDestination)\n          SELECT DISTINCT DiscussionTopic.discussionTopicUid AS discussionTopicUid,\n                 UserSession.usClientNodeId AS discussionTopicDestination\n            FROM ChangeLog\n                 JOIN DiscussionTopic\n                     ON ChangeLog.chTableId = 131\n                        AND ChangeLog.chEntityPk = DiscussionTopic.discussionTopicUid\n                        \n                        \n                 JOIN Clazz\n                      ON Clazz.clazzUid = DiscussionTopic.discussionTopicClazzUid\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                 \n           WHERE UserSession.usClientNodeId != (\n                 SELECT nodeClientId \n                   FROM SyncNode\n                  LIMIT 1)\n             AND DiscussionTopic.discussionTopicLct != COALESCE(\n                 (SELECT discussionTopicVersionId\n                    FROM discussionTopicReplicate\n                   WHERE discussionTopicPk = DiscussionTopic.discussionTopicUid\n                     AND DiscussionTopicDestination = UserSession.usClientNodeId), 0)\n         /*psql ON CONFLICT(discussionTopicPk, discussionTopicDestination) DO UPDATE\n             SET discussionTopicPending = true\n          */               \n    ")
  public actual abstract suspend fun replicateOnChange(): Unit

  @Query(`value` =
      "\n        SELECT DiscussionTopic.*,\n                ( \n                    SELECT COUNT(*) \n                      FROM DiscussionPost \n                     WHERE DiscussionPost.discussionPostDiscussionTopicUid = DiscussionTopic.discussionTopicUid\n                ) as numPosts,\n                (\n                    0\n                )as lastActiveTimestamp\n          FROM DiscussionTopic     \n         WHERE DiscussionTopic.discussionTopicCourseDiscussionUid = :discussionUid \n           AND CAST(DiscussionTopic.discussionTopicVisible AS INTEGER) = 1\n           AND CAST(DiscussionTopic.discussionTopicArchive AS INTEGER) = 0\n      ORDER BY DiscussionTopic.discussionTopicIndex\n    ")
  public actual abstract fun getListOfTopicsByDiscussion(discussionUid: Long):
      DataSource.Factory<Int, DiscussionTopicListDetail>

  @Query(`value` =
      "\n        SELECT DiscussionTopic.*\n          FROM DiscussionTopic\n         WHERE DiscussionTopic.discussionTopicCourseDiscussionUid IN \n                (SELECT CourseDiscussion.courseDiscussionUid \n                   FROM CourseDiscussion\n                  WHERE CourseDiscussion.courseDiscussionClazzUid = :clazzUid ) \n          AND CAST(DiscussionTopic.discussionTopicVisible AS INTEGER) = 1\n          AND CAST(DiscussionTopic.discussionTopicArchive AS INTEGER)  = 0\n                        \n    ")
  public actual abstract suspend fun getTopicsByClazz(clazzUid: Long): List<DiscussionTopic>

  @Query(`value` =
      "\n        SELECT DiscussionTopic.*\n          FROM DiscussionTopic\n         WHERE DiscussionTopic.discussionTopicUid = :discussionTopicUid\n         \n         ")
  public actual abstract fun getDiscussionTopicByUid(discussionTopicUid: Long):
      LiveData<DiscussionTopic?>

  @Query(`value` =
      "\n        UPDATE DiscussionTopic \n           SET discussionTopicVisible = :active, \n               discussionTopicLct = :changeTime\n         WHERE discussionTopicUid = :uid")
  public actual abstract suspend fun updateActiveByUid(
    uid: Long,
    active: Boolean,
    changeTime: Long,
  ): Unit

  @Insert(onConflict = 1)
  public actual abstract suspend fun replaceListAsync(list: List<DiscussionTopic>): Unit
}
