package com.ustadmobile.core.db.dao

import androidx.room.Dao
import androidx.room.Query
import com.ustadmobile.lib.db.entities.AgentEntity
import kotlin.Long
import kotlin.String
import kotlin.Unit

@Dao
public actual abstract class AgentDao : BaseDao<AgentEntity> {
  @Query(`value` =
      "\n     REPLACE INTO AgentEntityReplicate(aePk, aeDestination)\n      SELECT DISTINCT AgentEntity.agentUid AS aeUid,\n             :newNodeId AS aeDestination\n        FROM UserSession\n        JOIN PersonGroupMember \n               ON UserSession.usPersonUid = PersonGroupMember.groupMemberPersonUid\n               \n            JOIN ScopedGrant\n                 ON ScopedGrant.sgGroupUid = PersonGroupMember.groupMemberGroupUid\n                    AND (ScopedGrant.sgPermissions & \n                        64\n                        \n                                                    ) > 0\n            JOIN Person \n                 ON \n                ((ScopedGrant.sgTableId = -2\n                    AND ScopedGrant.sgEntityUid = -2)\n                 OR (ScopedGrant.sgTableId = 9\n                    AND ScopedGrant.sgEntityUid = Person.personUid)\n                 OR (ScopedGrant.sgTableId = 6       \n                    AND Person.personUid IN (\n                        SELECT DISTINCT clazzEnrolmentPersonUid\n                          FROM ClazzEnrolment\n                         WHERE clazzEnrolmentClazzUid =ScopedGrant.sgEntityUid \n                           AND ClazzEnrolment.clazzEnrolmentActive))\n                 OR (ScopedGrant.sgTableId = 164\n                    AND Person.personUid IN (\n                        SELECT DISTINCT schoolMemberPersonUid\n                          FROM SchoolMember\n                         WHERE schoolMemberSchoolUid = ScopedGrant.sgEntityUid\n                           AND schoolMemberActive))\n                           )    \n        \n        \n        JOIN AgentEntity \n             ON AgentEntity.agentPersonUid = Person.personUid\n       WHERE UserSession.usClientNodeId = :newNodeId\n         --notpsql \n         AND AgentEntity.agentLct != COALESCE(\n             (SELECT aeVersionId\n                FROM AgentEntityReplicate\n               WHERE aePk = AgentEntity.agentUid\n                 AND aeDestination = UserSession.usClientNodeId), 0) \n         --endnotpsql        \n      /*psql ON CONFLICT(aePk, aeDestination) DO UPDATE\n             SET aePending = (SELECT AgentEntity.agentLct\n                                FROM AgentEntity\n                               WHERE AgentEntity.agentUid = EXCLUDED.aePk ) \n                                     != AgentEntityReplicate.aePk\n      */       \n     ")
  public actual abstract suspend fun replicateOnNewNode(newNodeId: Long): Unit

  @Query(`value` =
      "\n     REPLACE INTO AgentEntityReplicate(aePk, aeDestination)\n      SELECT DISTINCT AgentEntity.agentUid AS aeUid,\n             UserSession.usClientNodeId AS aeDestination\n        FROM ChangeLog\n             JOIN AgentEntity\n                 ON ChangeLog.chTableId = 68\n                    AND ChangeLog.chEntityPk = AgentEntity.agentUid\n             JOIN Person \n                       ON Person.personUid = AgentEntity.agentPersonUid\n                  \n            JOIN ScopedGrant \n                   ON \n            ((ScopedGrant.sgTableId = -2\n                    AND ScopedGrant.sgEntityUid = -2)\n                 OR (ScopedGrant.sgTableId = 9\n                    AND ScopedGrant.sgEntityUid = Person.personUid)\n                 OR (ScopedGrant.sgTableId = 6       \n                    AND ScopedGrant.sgEntityUid IN (\n                        SELECT DISTINCT clazzEnrolmentClazzUid\n                          FROM ClazzEnrolment\n                         WHERE clazzEnrolmentPersonUid = Person.personUid \n                           AND ClazzEnrolment.clazzEnrolmentActive))\n                 OR (ScopedGrant.sgTableId = 164\n                    AND ScopedGrant.sgEntityUid IN (\n                        SELECT DISTINCT schoolMemberSchoolUid\n                          FROM SchoolMember\n                         WHERE schoolMemberPersonUid = Person.personUid\n                           AND schoolMemberActive))\n                           )\n        \n                   AND (ScopedGrant.sgPermissions & \n        \n                        64\n                        \n                                                     ) > 0\n             JOIN PersonGroupMember AS PrsGrpMbr\n                   ON ScopedGrant.sgGroupUid = PrsGrpMbr.groupMemberGroupUid\n              JOIN UserSession\n                   ON UserSession.usPersonUid = PrsGrpMbr.groupMemberPersonUid\n                      AND UserSession.usStatus = 1\n               \n       WHERE UserSession.usClientNodeId != (\n             SELECT nodeClientId \n               FROM SyncNode\n              LIMIT 1)\n         --notpsql \n         AND AgentEntity.agentLct != COALESCE(\n             (SELECT aeVersionId\n                FROM AgentEntityReplicate\n               WHERE aePk = AgentEntity.agentUid\n                 AND aeDestination = UserSession.usClientNodeId), 0) \n         --endnotpsql \n      /*psql ON CONFLICT(aePk, aeDestination) DO UPDATE\n             SET aePending = (SELECT AgentEntity.agentLct\n                                FROM AgentEntity\n                               WHERE AgentEntity.agentUid = EXCLUDED.aePk ) \n                                     != AgentEntityReplicate.aePk\n      */    \n    ")
  public actual abstract suspend fun replicateOnChange(): Unit

  @Query(`value` =
      "SELECT * FROM AgentEntity WHERE agentOpenId = :openId OR agentMbox = :mbox OR agentMbox_sha1sum = :sha1 OR (agentAccountName = :account AND agentHomePage = :homepage)")
  public actual abstract fun getAgentByAnyId(
    openId: String?,
    mbox: String?,
    account: String?,
    homepage: String?,
    sha1: String?,
  ): AgentEntity?

  @Query(`value` =
      "\n        SELECT *\n          FROM AgentEntity\n         WHERE agentAccountName = :username \n           AND agentHomePage = :endpoint\n    ")
  public actual abstract suspend fun getAgentFromPersonUsername(endpoint: String, username: String):
      AgentEntity?
}
