package com.ustadmobile.core.db.dao.xapi

import androidx.room.Dao
import androidx.room.Insert
import androidx.room.Query
import com.ustadmobile.lib.db.composites.xapi.StateIdAndLastModified
import com.ustadmobile.lib.db.entities.xapi.StateEntity
import kotlin.Any
import kotlin.Boolean
import kotlin.Long
import kotlin.collections.List

@Dao
public actual abstract class StateEntityDao {
  @Insert(
    onConflict = 1,
    entity = Any::class,
  )
  public actual abstract suspend fun upsertAsync(stateEntities: List<StateEntity>)

  @Query(`value` =
      "\n        SELECT StateEntity.*\n          FROM StateEntity\n         WHERE (SELECT ActorEntity.actorPersonUid\n                  FROM ActorEntity\n                 WHERE ActorEntity.actorUid = :actorUid) = :accountPersonUid\n           AND seActorUid = :actorUid\n           AND seHash = :seHash\n           AND (   CAST(:includeDeleted AS INTEGER) = 1 \n                OR CAST(StateEntity.seDeleted AS INTEGER) = 0)\n    ")
  public actual abstract suspend fun findByActorAndHash(
    accountPersonUid: Long,
    actorUid: Long,
    seHash: Long,
    includeDeleted: Boolean,
  ): StateEntity?

  @Query(`value` =
      "\n        SELECT StateEntity.*\n          FROM StateEntity\n         WHERE (SELECT ActorEntity.actorPersonUid\n                  FROM ActorEntity\n                 WHERE ActorEntity.actorUid = :actorUid) = :accountPersonUid\n           AND seActorUid = :actorUid\n           AND seActivityUid = :seActivityUid\n           AND (:modifiedSince = 0 OR StateEntity.seLastMod > :modifiedSince)\n           AND ((    :registrationUuidHi IS NULL\n                 AND StateEntity.seRegistrationHi IS NULL\n                 AND :registrationUuidLo IS NULL \n                 AND StateEntity.seRegistrationLo IS NULL)\n             OR (    StateEntity.seRegistrationHi = :registrationUuidHi \n                 AND StateEntity.seRegistrationLo = :registrationUuidLo))\n           AND StateEntity.seStateId IS NOT NULL  \n    ")
  public actual abstract suspend fun findByAgentAndActivity(
    accountPersonUid: Long,
    actorUid: Long,
    seActivityUid: Long,
    registrationUuidHi: Long?,
    registrationUuidLo: Long?,
    modifiedSince: Long,
  ): List<StateEntity>

  @Query(`value` =
      "\n        SELECT StateEntity.seStateId, StateEntity.seLastMod\n          FROM StateEntity\n         WHERE (SELECT ActorEntity.actorPersonUid\n                  FROM ActorEntity\n                 WHERE ActorEntity.actorUid = :actorUid) = :accountPersonUid\n           AND seActorUid = :actorUid\n           AND seActivityUid = :seActivityUid\n           AND (:modifiedSince = 0 OR StateEntity.seLastMod > :modifiedSince)\n           AND ((    :registrationUuidHi IS NULL\n                 AND StateEntity.seRegistrationHi IS NULL\n                 AND :registrationUuidLo IS NULL \n                 AND StateEntity.seRegistrationLo IS NULL)\n             OR (    StateEntity.seRegistrationHi = :registrationUuidHi \n                 AND StateEntity.seRegistrationLo = :registrationUuidLo))\n           AND StateEntity.seStateId IS NOT NULL \n           AND CAST(StateEntity.seDeleted AS INTEGER) = 0      \n    ")
  public actual abstract suspend fun getStateIds(
    accountPersonUid: Long,
    actorUid: Long,
    seActivityUid: Long,
    registrationUuidHi: Long?,
    registrationUuidLo: Long?,
    modifiedSince: Long,
  ): List<StateIdAndLastModified>

  @Query(`value` =
      "\n        SELECT StateEntity.*\n          FROM StateEntity\n         WHERE (SELECT ActorEntity.actorPersonUid\n                  FROM ActorEntity\n                 WHERE ActorEntity.actorUid = :actorUid) = :accountPersonUid\n           AND seActorUid = :actorUid\n           AND seActivityUid = :seActivityUid \n           AND ((    :registrationUuidHi IS NULL\n                 AND StateEntity.seRegistrationHi IS NULL\n                 AND :registrationUuidLo IS NULL \n                 AND StateEntity.seRegistrationLo IS NULL)\n             OR (    StateEntity.seRegistrationHi = :registrationUuidHi \n                 AND StateEntity.seRegistrationLo = :registrationUuidLo))\n           AND StateEntity.seH5PSubContentId IS NOT NULL      \n           AND CAST(StateEntity.seH5PPreloaded AS INTEGER) = 1      \n    ")
  public actual abstract suspend fun getH5PPreload(
    accountPersonUid: Long,
    actorUid: Long,
    seActivityUid: Long,
    registrationUuidHi: Long?,
    registrationUuidLo: Long?,
  ): List<StateEntity>
}
