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.ContainerEntryFile
import com.ustadmobile.lib.db.entities.ContainerEntryFileUidAndPath
import kotlin.Int
import kotlin.Long
import kotlin.String
import kotlin.Unit
import kotlin.collections.List

@Dao
public actual abstract class ContainerEntryFileDao : BaseDao<ContainerEntryFile> {
  @Insert(onConflict = 3)
  public actual abstract suspend fun insertListAsync(list: List<ContainerEntryFile>): Unit

  @Query(`value` = "SELECT ContainerEntryFile.* FROM ContainerEntryFile WHERE cefMd5 IN (:md5Sums)")
  public actual abstract fun findEntriesByMd5Sums(md5Sums: List<String>): List<ContainerEntryFile>

  @Query(`value` = "SELECT ContainerEntryFile.* FROM ContainerEntryFile WHERE cefMd5 IN (:md5Sums)")
  public actual abstract suspend fun findEntriesByMd5SumsAsync(md5Sums: List<String>):
      List<ContainerEntryFile>

  @Query(`value` =
      "SELECT ContainerEntryFile.cefMd5 FROM ContainerEntryFile WHERE cefMd5 IN (:md5Sums)")
  public actual abstract suspend fun findExistingMd5SumsByMd5SumsAsync(md5Sums: List<String>):
      List<String?>

  @Query(`value` = "SELECT ContainerEntryFile.* FROM ContainerEntryFile WHERE cefUid IN (:uidList)")
  public actual abstract fun findEntriesByUids(uidList: List<Long>): List<ContainerEntryFile>

  @Query(`value` = "UPDATE ContainerEntryFile SET cefPath = :path WHERE cefUid = :cefUid")
  public actual abstract fun updateFilePath(cefUid: Long, path: String): Unit

  @Query(`value` = "SELECT * FROM ContainerEntryFile WHERE cefUid = :uid")
  public actual abstract fun findByUid(uid: Long): ContainerEntryFile?

  @Query(`value` =
      "SELECT SUM(ContainerEntryFile.ceCompressedSize) FROM ContainerEntry JOIN ContainerEntryFile ON ContainerEntry.ceCefUid = ContainerEntryFile.cefUid WHERE ContainerEntry.ceContainerUid = :containerUid")
  public actual abstract fun sumContainerFileEntrySizes(containerUid: Long): Long

  @Query(`value` =
      "SELECT * FROM ContainerEntryFile WHERE compression = 0 AND NOT EXISTS(SELECT * FROM ContainerEntry WHERE ceCefUid = ContainerEntryFile.cefUid AND (ContainerEntry.cePath LIKE '%.webm' OR ContainerEntry.cePath LIKE '%.mp4')) LIMIT 100")
  public actual abstract suspend fun getAllFilesForCompression(): List<ContainerEntryFile>

  @Query(`value` =
      "UPDATE ContainerEntryFile SET compression = :compression, ceCompressedSize = :ceCompressedSize WHERE cefUid = :cefUid")
  public actual abstract fun updateCompressedFile(
    compression: Int,
    ceCompressedSize: Long,
    cefUid: Long,
  ): Unit

  @Query(`value` =
      "SELECT ContainerEntryFile.* \n                      FROM ContainerEntryFile \n                     WHERE NOT EXISTS (SELECT ContainerEntry.ceCefUid \n                                     FROM ContainerEntry \n                                    WHERE ContainerEntryFile.cefUid = ContainerEntry.ceCefUid) \n                     LIMIT 100")
  public actual abstract fun findZombieEntries(): List<ContainerEntryFile>

  @Query(`value` =
      "\n        SELECT cefUid, cefPath\n          FROM ContainerEntryFile\n         WHERE NOT EXISTS \n               (SELECT ContainerEntry.ceCefUid \n                  FROM ContainerEntry \n                 WHERE ContainerEntry.ceCefUid = ContainerEntryFile.cefUid \n                 LIMIT 1)\n         LIMIT :limit     \n    ")
  public actual abstract suspend fun findZombieUidsAndPath(limit: Int):
      List<ContainerEntryFileUidAndPath>

  @Query(`value` =
      "\n        DELETE FROM ContainerEntryFile\n              WHERE cefUid IN (:uidList) \n    ")
  public actual abstract suspend fun deleteByUidList(uidList: List<Long>): Unit

  @Delete
  public actual abstract fun deleteListOfEntryFiles(entriesToDelete: List<ContainerEntryFile>): Unit

  @Query(`value` = "SELECT ContainerEntryFile.* FROM ContainerEntryFile WHERE cefMd5 = :md5Sum")
  public actual abstract suspend fun findEntryByMd5Sum(md5Sum: String): ContainerEntryFile?
}
