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.Any
import kotlin.Boolean
import kotlin.Long
import kotlin.collections.List

@Dao
public actual abstract class ContentEntryParentChildJoinDao : BaseDao<ContentEntryParentChildJoin> {
  @Insert(
    entity = Any::class,
    onConflict = 3,
  )
  public actual abstract suspend fun insertListAsync(entityList: List<ContentEntryParentChildJoin>)

  @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` =
      "\n        SELECT * \n          FROM ContentEntryParentChildJoin \n         WHERE cepcjParentContentEntryUid = :parentUid\n    ")
  public actual abstract suspend 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,
    entity = Any::class,
  )
  public actual abstract fun replaceList(entries: List<ContentEntryParentChildJoin>)

  @Insert(
    onConflict = 1,
    entity = Any::class,
  )
  public actual abstract fun insertWithReplace(parentChildJoinDao: ContentEntryParentChildJoin)

  @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,
  )

  @Query(`value` =
      "\n        UPDATE ContentEntryParentChildJoin\n           SET cepcjDeleted = :isDeleted,\n               cepcjLct = :updateTime\n         WHERE cepcjUid IN (:selectedUids) \n    ")
  public actual abstract suspend fun setEntriesDeleted(
    selectedUids: List<Long>,
    isDeleted: Boolean,
    updateTime: Long,
  )

  @Query(`value` =
      "\n        SELECT ContentEntryParentChildJoin.*\n          FROM ContentEntryParentChildJoin\n         WHERE  ContentEntryParentChildJoin.cepcjUid = :uid\n    ")
  public actual abstract suspend fun findByUid(uid: Long): ContentEntryParentChildJoin?
}
