package com.ustadmobile.core.db.dao

import androidx.room.Dao
import androidx.room.Insert
import androidx.room.Query
import com.ustadmobile.lib.db.entities.SiteTerms
import com.ustadmobile.lib.db.entities.SiteTermsWithLanguage
import kotlin.Any
import kotlin.Boolean
import kotlin.Int
import kotlin.Long
import kotlin.String
import kotlin.collections.List
import kotlinx.coroutines.flow.Flow

@Dao
public actual abstract class SiteTermsDao : OneToManyJoinDao<SiteTerms> {
  @Query(`value` =
      "\n        SELECT * FROM SiteTerms WHERE sTermsUid = coalesce(\n            (SELECT sTermsUid FROM SiteTerms st_int WHERE st_int.sTermsLang = :langCode LIMIT 1),\n            (SELECT sTermsUid FROM SiteTerms st_int WHERE st_int.sTermsLang = 'en' LIMIT 1),\n            0)\n    ")
  public actual abstract suspend fun findSiteTerms(langCode: String): SiteTerms?

  @Insert(
    entity = Any::class,
    onConflict = 3,
  )
  public actual abstract suspend fun insertAsync(siteTerms: SiteTerms): Long

  @Query(`value` = "SELECT * FROM SiteTerms WHERE sTermsUid = :uid")
  public actual abstract suspend fun findByUidAsync(uid: Long): SiteTerms?

  @Query(`value` =
      "\n        SELECT SiteTerms.*\n          FROM SiteTerms\n         WHERE :activeOnly = 0 \n            OR CAST(sTermsActive AS INTEGER) = 1\n    ")
  public actual abstract fun findAllTermsAsListFlow(activeOnly: Int): Flow<List<SiteTerms>>

  @Query(`value` =
      "\n        SELECT SiteTerms.*\n          FROM SiteTerms\n         WHERE :activeOnly = 0 \n            OR CAST(sTermsActive AS INTEGER) = 1\n    ")
  public actual abstract suspend fun findAllTerms(activeOnly: Int): List<SiteTerms>

  @Query(`value` =
      "SELECT SiteTerms.*, Language.*\n        FROM SiteTerms\n        LEFT JOIN Language ON SiteTerms.sTermsLangUid = Language.langUid\n        WHERE CAST(sTermsActive AS INTEGER) = 1\n    ")
  public actual abstract suspend fun findAllWithLanguageAsList(): List<SiteTermsWithLanguage>

  @Insert(
    onConflict = 1,
    entity = Any::class,
  )
  public actual abstract suspend fun upsertList(termList: List<SiteTerms>)

  @Query(`value` =
      "\n        UPDATE SiteTerms \n           SET sTermsActive = :active,\n               sTermsLct = :changeTime\n         WHERE sTermsUid = :sTermsUid\n        ")
  public actual abstract suspend fun updateActiveByUid(
    sTermsUid: Long,
    active: Boolean,
    changeTime: Long,
  )

  @Query(`value` =
      "\n        SELECT SiteTerms.sTermsLang\n          FROM SiteTerms\n         WHERE CAST(SiteTerms.sTermsActive AS INTEGER) = :active \n    ")
  public actual abstract suspend fun findAvailableSiteTermLanguages(active: Int): List<String?>

  @Query(`value` =
      "\n        SELECT SiteTerms.*\n          FROM SiteTerms\n         WHERE SiteTerms.sTermsLang = :lang\n           AND CAST(SiteTerms.sTermsActive AS INTEGER) = 1\n      ORDER BY SiteTerms.sTermsLct DESC\n         LIMIT 1     \n    ")
  public actual abstract suspend fun findLatestByLanguage(lang: String): SiteTerms?
}
