package com.ustadmobile.core.db.dao

import androidx.room.Dao
import androidx.room.Insert
import androidx.room.Query
import com.ustadmobile.lib.db.entities.ContentEntry
import com.ustadmobile.lib.db.entities.ContentEntryParentChildJoin
import kotlin.Long
import kotlin.Unit
import kotlin.collections.List

@Dao
public actual abstract class ContentEntryParentChildJoinDao : BaseDao<ContentEntryParentChildJoin> {
  @Query(`value` =
      "\n     REPLACE INTO ContentEntryParentChildJoinReplicate(cepcjPk, cepcjDestination)\n      SELECT DISTINCT ContentEntryParentChildJoin.cepcjUid AS cepcjUid,\n             :newNodeId AS cepcjDestination\n        FROM ContentEntryParentChildJoin\n       WHERE ContentEntryParentChildJoin.cepcjLct != COALESCE(\n             (SELECT cepcjVersionId\n                FROM ContentEntryParentChildJoinReplicate\n               WHERE cepcjPk = ContentEntryParentChildJoin.cepcjUid\n                 AND cepcjDestination = :newNodeId), -1) \n      /*psql ON CONFLICT(cepcjPk, cepcjDestination) DO UPDATE\n             SET cepcjPending = true\n      */       \n    ")
  public actual abstract suspend fun replicateOnNewNode(newNodeId: Long): Unit

  @Query(`value` =
      "\n    REPLACE INTO ContentEntryParentChildJoinReplicate(cepcjPk, cepcjDestination)\n    SELECT DISTINCT ContentEntryParentChildJoin.cepcjUid AS cepcjUid,\n         UserSession.usClientNodeId AS cepcjDestination\n    FROM ChangeLog\n         JOIN ContentEntryParentChildJoin\n             ON ChangeLog.chTableId = 7\n                AND ChangeLog.chEntityPk = ContentEntryParentChildJoin.cepcjUid\n         JOIN UserSession ON UserSession.usStatus = 1\n    WHERE UserSession.usClientNodeId != (\n         SELECT nodeClientId \n           FROM SyncNode\n          LIMIT 1)\n     AND ContentEntryParentChildJoin.cepcjLct != COALESCE(\n         (SELECT cepcjVersionId\n            FROM ContentEntryParentChildJoinReplicate\n           WHERE cepcjPk = ContentEntryParentChildJoin.cepcjUid\n             AND cepcjDestination = UserSession.usClientNodeId), 0)\n    /*psql ON CONFLICT(cepcjPk, cepcjDestination) DO UPDATE\n     SET cepcjPending = true\n    */               \n    ")
  public actual abstract suspend fun replicateOnChange(): Unit

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

  @Query(`value` =
      "SELECT ContentEntryParentChildJoin.* FROM ContentEntryParentChildJoin LEFT JOIN ContentEntry parentEntry ON ContentEntryParentChildJoin.cepcjParentContentEntryUid = parentEntry.contentEntryUid LEFT JOIN ContentEntry childEntry ON ContentEntryParentChildJoin.cepcjChildContentEntryUid = childEntry.contentEntryUid WHERE parentEntry.publik AND childEntry.publik")
  public actual abstract fun publicContentEntryParentChildJoins(): List<ContentEntryParentChildJoin>

  @Query(`value` = "SELECT * FROM ContentEntryParentChildJoin")
  public actual abstract fun all(): List<ContentEntryParentChildJoin>

  @Query(`value` =
      "SELECT * FROM ContentEntryParentChildJoin WHERE cepcjChildContentEntryUid = :childEntryContentUid LIMIT 1")
  public actual abstract fun findParentByChildUuids(childEntryContentUid: Long):
      ContentEntryParentChildJoin?

  @Query(`value` =
      "SELECT * FROM ContentEntryParentChildJoin WHERE cepcjChildContentEntryUid = :childEntryContentUid")
  public actual abstract fun findListOfParentsByChildUuid(childEntryContentUid: Long):
      List<ContentEntryParentChildJoin>

  @Query(`value` =
      "SELECT * FROM ContentEntryParentChildJoin WHERE cepcjParentContentEntryUid = :parentUid")
  public actual abstract fun findListOfChildsByParentUuid(parentUid: Long):
      List<ContentEntryParentChildJoin>

  @Query(`value` =
      "SELECT * FROM ContentEntryParentChildJoin WHERE cepcjParentContentEntryUid = :parentUid AND cepcjChildContentEntryUid = :childUid LIMIT 1")
  public actual abstract fun findJoinByParentChildUuids(parentUid: Long, childUid: Long):
      ContentEntryParentChildJoin?

  @Query(`value` =
      "SELECT ContentEntry.* FROM ContentEntry WHERE NOT EXISTS(SELECT cepcjUid FROM ContentEntryParentChildJoin WHERE cepcjChildContentEntryUid = ContentEntry.contentEntryUid) AND EXISTS(SELECT cepcjUid FROM ContentEntryParentChildJoin WHERE cepcjParentContentEntryUid = ContentEntry.contentEntryUid)")
  public actual abstract suspend fun selectTopEntries(): List<ContentEntry>

  @Insert(onConflict = 1)
  public actual abstract fun replaceList(entries: List<ContentEntryParentChildJoin>): Unit

  @Insert(onConflict = 1)
  public actual abstract fun insertWithReplace(parentChildJoinDao: ContentEntryParentChildJoin):
      Unit

  @Query(`value` =
      "\n        UPDATE ContentEntryParentChildJoin \n           SET cepcjParentContentEntryUid = :contentEntryUid, \n               cepcjLct = :updateTime \n               WHERE cepcjUid IN (:selectedItems)\n    ")
  public actual abstract suspend fun moveListOfEntriesToNewParent(
    contentEntryUid: Long,
    selectedItems: List<Long>,
    updateTime: Long,
  ): Unit
}
