package com.ustadmobile.core.db.dao

import androidx.room.Dao
import androidx.room.Delete
import androidx.room.Insert
import androidx.room.Query
import com.ustadmobile.lib.db.entities.ContainerEntry
import com.ustadmobile.lib.db.entities.ContainerEntryWithContainerEntryFile
import com.ustadmobile.lib.db.entities.ContainerEntryWithMd5
import kotlin.Long
import kotlin.String
import kotlin.Unit
import kotlin.collections.List

@Dao
public actual abstract class ContainerEntryDao : BaseDao<ContainerEntry> {
  @Insert(onConflict = 3)
  public actual abstract suspend fun insertListAsync(containerEntryList: List<ContainerEntry>): Unit

  @Query(`value` =
      "SELECT ContainerEntry.*, ContainerEntryFile.* FROM ContainerEntry LEFT JOIN ContainerEntryFile ON ContainerEntry.ceCefUid = ContainerEntryFile.cefUid WHERE ContainerEntry.ceContainerUid = :containerUid")
  public actual abstract fun findByContainer(containerUid: Long):
      List<ContainerEntryWithContainerEntryFile>

  @Query(`value` =
      "SELECT ContainerEntry.*, ContainerEntryFile.* FROM ContainerEntry LEFT JOIN ContainerEntryFile ON ContainerEntry.ceCefUid = ContainerEntryFile.cefUid WHERE ContainerEntry.ceContainerUid = :containerUid AND ContainerEntry.cePath = :pathInContainer")
  public actual abstract fun findByPathInContainer(containerUid: Long, pathInContainer: String):
      ContainerEntryWithContainerEntryFile?

  @Query(`value` =
      "SELECT ContainerEntry.*, ContainerEntryFile.cefMd5 AS cefMd5 FROM ContainerEntry LEFT JOIN ContainerEntryFile ON ContainerEntry.ceCefUid = ContainerEntryFile.cefUid WHERE ContainerEntry.ceContainerUid = :containerUid")
  public actual abstract fun findByContainerWithMd5(containerUid: Long): List<ContainerEntryWithMd5>

  @Query(`value` =
      "SELECT ContainerEntry.*, ContainerEntryFile.* FROM ContainerEntry LEFT JOIN ContainerEntryFile ON ContainerEntry.ceCefUid = ContainerEntryFile.cefUid WHERE ContainerEntry.ceContainerUid = :containerUid")
  public actual abstract suspend fun findByContainerAsync(containerUid: Long):
      List<ContainerEntryWithContainerEntryFile>

  @Query(`value` = "DELETE FROM ContainerEntry WHERE ceContainerUid = :containerUid")
  public actual abstract fun deleteByContainerUid(containerUid: Long): Unit

  @Delete
  public actual abstract fun deleteList(entries: List<ContainerEntry>): Unit

  @Query(`value` =
      "\n            DELETE FROM ContainerEntry \n             WHERE ceContainerUid \n                IN (SELECT cjiContainerUid \n                      FROM ContentJobItem\n                      JOIN ContentJob \n                           ON ContentJobItem.cjiJobUid = ContentJob.cjUid\n                     WHERE ContentJob.cjUid = :jobId)")
  public actual abstract suspend fun deleteContainerEntriesCreatedByJobs(jobId: Long): Unit

  @Query(`value` =
      "\n        DELETE FROM ContainerEntry\n         WHERE ceContainerUid\n            IN (SELECT containerUid\n                  FROM Container\n                 WHERE containerContentEntryUid = :contentEntryUid) \n    ")
  public actual abstract fun deleteByContentEntryUid(contentEntryUid: Long): Unit

  @Query(`value` =
      "\n        INSERT INTO ContainerEntry(ceContainerUid, cePath, ceCefUid) \n        SELECT :containerUid AS ceContainerUid, :path AS cePath, \n               (SELECT COALESCE(\n                      (SELECT cefUid \n                         FROM ContainerEntryFile\n                        WHERE cefMd5 = :md5\n                        LIMIT 1), 0))  \n    ")
  public actual abstract suspend fun insertWithMd5SumsAsync(
    containerUid: Long,
    path: String,
    md5: String,
  ): Unit
}
