package com.ustadmobile.core.db.dao

import androidx.paging.DataSource
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.Boolean
import kotlin.Int
import kotlin.Long
import kotlin.String
import kotlin.Unit
import kotlin.collections.List

@Dao
public actual abstract class SiteTermsDao : OneToManyJoinDao<SiteTerms> {
  @Query(`value` =
      "\n     REPLACE INTO SiteTermsReplicate(stPk, stDestination)\n      SELECT DISTINCT SiteTerms.sTermsUid AS stPk,\n             :newNodeId AS stDestination\n        FROM SiteTerms\n       WHERE SiteTerms.sTermsLct != COALESCE(\n             (SELECT stVersionId\n                FROM SiteTermsReplicate\n               WHERE stPk = SiteTerms.sTermsUid\n                 AND stDestination = :newNodeId), 0) \n      /*psql ON CONFLICT(stPk, stDestination) DO UPDATE\n             SET stPending = true\n      */       \n    ")
  public actual abstract suspend fun replicateOnNewNode(newNodeId: Long): Unit

  @Query(`value` =
      "\n REPLACE INTO SiteTermsReplicate(stPk, stDestination)\n  SELECT DISTINCT SiteTerms.sTermsUid AS stUid,\n         UserSession.usClientNodeId AS stDestination\n    FROM ChangeLog\n         JOIN SiteTerms\n             ON ChangeLog.chTableId = 272\n                AND ChangeLog.chEntityPk = SiteTerms.sTermsUid\n         JOIN UserSession ON UserSession.usStatus = 1\n   WHERE UserSession.usClientNodeId != (\n         SELECT nodeClientId \n           FROM SyncNode\n          LIMIT 1)\n     AND SiteTerms.sTermsLct != COALESCE(\n         (SELECT stVersionId\n            FROM SiteTermsReplicate\n           WHERE stPk = SiteTerms.sTermsUid\n             AND stDestination = UserSession.usClientNodeId), 0)\n /*psql ON CONFLICT(stPk, stDestination) DO UPDATE\n     SET stPending = true\n  */               \n ")
  public actual abstract suspend fun replicateOnChange(): Unit

  @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(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` =
      "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 fun findAllTermsAsFactory(): DataSource.Factory<Int, SiteTermsWithLanguage>

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

  @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,
  ): Unit
}
