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

import com.ustadmobile.door.DoorConstants
import com.ustadmobile.door.ext.doorWrapperNodeId
import com.ustadmobile.door.ext.requirePagingSourceLoadParams
import com.ustadmobile.door.http.DoorHttpServerConfig
import com.ustadmobile.door.http.DoorJsonRequest
import com.ustadmobile.door.http.DoorJsonResponse
import com.ustadmobile.door.log.DoorLogLevel
import com.ustadmobile.door.message.DoorMessage
import com.ustadmobile.door.paging.loadPageDataForHttp
import com.ustadmobile.door.replication.DoorReplicationEntity
import com.ustadmobile.lib.db.entities.Person
import com.ustadmobile.lib.db.entities.PersonPicture
import com.ustadmobile.lib.db.entities.xapi.ActivityEntity
import com.ustadmobile.lib.db.entities.xapi.ActivityLangMapEntry
import com.ustadmobile.lib.db.entities.xapi.ActorEntity
import com.ustadmobile.lib.db.entities.xapi.GroupMemberActorJoin
import com.ustadmobile.lib.db.entities.xapi.StatementEntity
import com.ustadmobile.lib.db.entities.xapi.VerbEntity
import com.ustadmobile.lib.db.entities.xapi.VerbLangMapEntry
import kotlin.Int
import kotlin.Long
import kotlin.String
import kotlin.Suppress
import kotlin.collections.List
import kotlin.collections.buildList
import kotlinx.coroutines.flow.first
import kotlinx.serialization.builtins.ListSerializer
import kotlinx.serialization.builtins.nullable
import kotlinx.serialization.builtins.serializer
import kotlinx.serialization.json.jsonObject

@Suppress("LocalVariableName", "RedundantSuppression", "FunctionName",
    "RedundantVisibilityModifier")
public suspend
    fun StatementDao.findStatusForStudentsInClazzAsFlow_DoorHttp(serverConfig: DoorHttpServerConfig,
    request: DoorJsonRequest): DoorJsonResponse {
  val json = serverConfig.json
  val _arg_clazzUid : Long = request.queryParam("clazzUid")?.let {
    json.decodeFromString(Long.serializer(), it)
  } ?: 0L
  val _arg_studentPersonUids : List<Long> = request.queryParam("studentPersonUids")?.let {
    json.decodeFromString(ListSerializer(Long.serializer()), it)
  } ?: mutableListOf()
  val _arg_accountPersonUid : Long = request.queryParam("accountPersonUid")?.let {
    json.decodeFromString(Long.serializer(), it)
  } ?: 0L
  val _result_findStatusForStudentsInClazzByUidList = findStatusForStudentsInClazzByUidList(
    clazzUid = _arg_clazzUid,
    studentPersonUids = _arg_studentPersonUids,
    completionOrProgressTrueVal = true,
  )
  val _result_findActorEntitiesForStudentInClazzByUidList =
      findActorEntitiesForStudentInClazzByUidList(
    clazzUid = _arg_clazzUid,
    studentPersonUids = _arg_studentPersonUids,
    accountPersonUid = _arg_accountPersonUid,
  )
  val replicationEntities = buildList<DoorReplicationEntity> {
    addAll(
      _result_findStatusForStudentsInClazzByUidList.mapNotNull {
        _row ->
        _row.statementEntity?.let {
          DoorReplicationEntity(tableId = 60,
            orUid = 0,
            entity = json.encodeToJsonElement(StatementEntity.serializer(), it).jsonObject,
          )
        }

      }
    )
    addAll(
      _result_findStatusForStudentsInClazzByUidList.mapNotNull {
        _row ->
        _row.groupMemberActorJoin?.let {
          DoorReplicationEntity(tableId = 4_232,
            orUid = 0,
            entity = json.encodeToJsonElement(GroupMemberActorJoin.serializer(), it).jsonObject,
          )
        }

      }
    )
    addAll(
      _result_findStatusForStudentsInClazzByUidList.mapNotNull {
        _row ->
        _row.actorEntity?.let {
          DoorReplicationEntity(tableId = 68,
            orUid = 0,
            entity = json.encodeToJsonElement(ActorEntity.serializer(), it).jsonObject,
          )
        }

      }
    )
    addAll(
      _result_findActorEntitiesForStudentInClazzByUidList.map {
        _row ->
        DoorReplicationEntity(tableId = 68,
          orUid = 0,
          entity = json.encodeToJsonElement(ActorEntity.serializer(), _row).jsonObject,
        )
      }
    )
  }
  val _thisNodeId = request.db.doorWrapperNodeId
  return DoorJsonResponse(
    headers = buildList {
      add(Pair(DoorConstants.HEADER_NODE_ID, _thisNodeId.toString()))
    }
    ,
    bodyText = json.encodeToString(
      DoorMessage.serializer(),
      DoorMessage(
        what = DoorMessage.WHAT_REPLICATION_PULL,
        fromNode = _thisNodeId,
        toNode = request.requireNodeId(),
        replications = replicationEntities,
      )
    )
  )
}

@Suppress("LocalVariableName", "RedundantSuppression", "FunctionName",
    "RedundantVisibilityModifier")
public suspend fun StatementDao.findPersonsWithAttempts_DoorHttp(serverConfig: DoorHttpServerConfig,
    request: DoorJsonRequest): DoorJsonResponse {
  val json = serverConfig.json
  val _arg_contentEntryUid : Long = request.queryParam("contentEntryUid")?.let {
    json.decodeFromString(Long.serializer(), it)
  } ?: 0L
  val _arg_accountPersonUid : Long = request.queryParam("accountPersonUid")?.let {
    json.decodeFromString(Long.serializer(), it)
  } ?: 0L
  val _arg_searchText : String? = request.queryParam("searchText")?.let {
    json.decodeFromString(String.serializer().nullable, it)
  }
  val _arg_sortOrder : Int = request.queryParam("sortOrder")?.let {
    json.decodeFromString(Int.serializer(), it)
  } ?: 0
  val _pagingLoadParams = request.requirePagingSourceLoadParams(
    json = json,
    keyDeserializationStrategy = Int.serializer().nullable,
  )

  val _result_findPersonsWithAttempts_pagingSource = findPersonsWithAttempts(
    contentEntryUid = _arg_contentEntryUid,
    accountPersonUid = _arg_accountPersonUid,
    searchText = _arg_searchText,
    sortOrder = _arg_sortOrder,
  ).loadPageDataForHttp(_pagingLoadParams)
  val _result_findPersonsWithAttempts = _result_findPersonsWithAttempts_pagingSource.data
  serverConfig.logger.log(DoorLogLevel.VERBOSE,
      "DoorPaging: loaded from: ${_pagingLoadParams.key} endOfPaginationReached=${_result_findPersonsWithAttempts_pagingSource.endOfPaginationReached}")
  val _endOfPaginationReached = _result_findPersonsWithAttempts_pagingSource.endOfPaginationReached

  val _result_findPersonsWithAttemptsStatements = findPersonsWithAttemptsStatements(
    contentEntryUid = _arg_contentEntryUid,
    accountPersonUid = _arg_accountPersonUid,
    searchText = _arg_searchText,
  )
  val replicationEntities = buildList<DoorReplicationEntity> {
    addAll(
      _result_findPersonsWithAttempts.map {
        _row ->
        DoorReplicationEntity(tableId = 9,
          orUid = 0,
          entity = json.encodeToJsonElement(Person.serializer(), _row.person).jsonObject,
        )
      }
    )
    addAll(
      _result_findPersonsWithAttempts.mapNotNull {
        _row ->
        _row.picture?.let {
          DoorReplicationEntity(tableId = 50,
            orUid = 0,
            entity = json.encodeToJsonElement(PersonPicture.serializer(), it).jsonObject,
          )
        }

      }
    )
    addAll(
      _result_findPersonsWithAttemptsStatements.map {
        _row ->
        DoorReplicationEntity(tableId = 60,
          orUid = 0,
          entity = json.encodeToJsonElement(StatementEntity.serializer(), _row).jsonObject,
        )
      }
    )
  }
  val _thisNodeId = request.db.doorWrapperNodeId
  return DoorJsonResponse(
    headers = buildList {
      add(Pair(DoorConstants.HEADER_NODE_ID, _thisNodeId.toString()))
      add(Pair(DoorConstants.HEADER_PAGING_END_REACHED, _endOfPaginationReached.toString()))
    }
    ,
    bodyText = json.encodeToString(
      DoorMessage.serializer(),
      DoorMessage(
        what = DoorMessage.WHAT_REPLICATION_PULL,
        fromNode = _thisNodeId,
        toNode = request.requireNodeId(),
        replications = replicationEntities,
      )
    )
  )
}

@Suppress("LocalVariableName", "RedundantSuppression", "FunctionName",
    "RedundantVisibilityModifier")
public suspend
    fun StatementDao.findSessionsByPersonAndContent_DoorHttp(serverConfig: DoorHttpServerConfig,
    request: DoorJsonRequest): DoorJsonResponse {
  val json = serverConfig.json
  val _arg_contentEntryUid : Long = request.queryParam("contentEntryUid")?.let {
    json.decodeFromString(Long.serializer(), it)
  } ?: 0L
  val _arg_personUid : Long = request.queryParam("personUid")?.let {
    json.decodeFromString(Long.serializer(), it)
  } ?: 0L
  val _arg_accountPersonUid : Long = request.queryParam("accountPersonUid")?.let {
    json.decodeFromString(Long.serializer(), it)
  } ?: 0L
  val _arg_sortOrder : Int = request.queryParam("sortOrder")?.let {
    json.decodeFromString(Int.serializer(), it)
  } ?: 0
  val _pagingLoadParams = request.requirePagingSourceLoadParams(
    json = json,
    keyDeserializationStrategy = Int.serializer().nullable,
  )

  val _result_findSessionsByPersonAndContentStatements = findSessionsByPersonAndContentStatements(
    contentEntryUid = _arg_contentEntryUid,
    personUid = _arg_personUid,
    accountPersonUid = _arg_accountPersonUid,
  )
  val _result_findSessionsByPersonAndContent_pagingSource = findSessionsByPersonAndContent(
    contentEntryUid = _arg_contentEntryUid,
    personUid = _arg_personUid,
    accountPersonUid = _arg_accountPersonUid,
    sortOrder = _arg_sortOrder,
  ).loadPageDataForHttp(_pagingLoadParams)
  val _result_findSessionsByPersonAndContent =
      _result_findSessionsByPersonAndContent_pagingSource.data
  serverConfig.logger.log(DoorLogLevel.VERBOSE,
      "DoorPaging: loaded from: ${_pagingLoadParams.key} endOfPaginationReached=${_result_findSessionsByPersonAndContent_pagingSource.endOfPaginationReached}")
  val _endOfPaginationReached =
      _result_findSessionsByPersonAndContent_pagingSource.endOfPaginationReached

  val replicationEntities = buildList<DoorReplicationEntity> {
    addAll(
      _result_findSessionsByPersonAndContentStatements.map {
        _row ->
        DoorReplicationEntity(tableId = 60,
          orUid = 0,
          entity = json.encodeToJsonElement(StatementEntity.serializer(), _row).jsonObject,
        )
      }
    )
  }
  val _thisNodeId = request.db.doorWrapperNodeId
  return DoorJsonResponse(
    headers = buildList {
      add(Pair(DoorConstants.HEADER_NODE_ID, _thisNodeId.toString()))
      add(Pair(DoorConstants.HEADER_PAGING_END_REACHED, _endOfPaginationReached.toString()))
    }
    ,
    bodyText = json.encodeToString(
      DoorMessage.serializer(),
      DoorMessage(
        what = DoorMessage.WHAT_REPLICATION_PULL,
        fromNode = _thisNodeId,
        toNode = request.requireNodeId(),
        replications = replicationEntities,
      )
    )
  )
}

@Suppress("LocalVariableName", "RedundantSuppression", "FunctionName",
    "RedundantVisibilityModifier")
public suspend fun StatementDao.findStatementsBySession_DoorHttp(serverConfig: DoorHttpServerConfig,
    request: DoorJsonRequest): DoorJsonResponse {
  val json = serverConfig.json
  val _arg_registrationHi : Long = request.queryParam("registrationHi")?.let {
    json.decodeFromString(Long.serializer(), it)
  } ?: 0L
  val _arg_registrationLo : Long = request.queryParam("registrationLo")?.let {
    json.decodeFromString(Long.serializer(), it)
  } ?: 0L
  val _arg_accountPersonUid : Long = request.queryParam("accountPersonUid")?.let {
    json.decodeFromString(Long.serializer(), it)
  } ?: 0L
  val _arg_selectedPersonUid : Long = request.queryParam("selectedPersonUid")?.let {
    json.decodeFromString(Long.serializer(), it)
  } ?: 0L
  val _arg_contentEntryUid : Long = request.queryParam("contentEntryUid")?.let {
    json.decodeFromString(Long.serializer(), it)
  } ?: 0L
  val _arg_searchText : String = request.queryParam("searchText")?.let {
    json.decodeFromString(String.serializer(), it)
  } ?: ""
  val _arg_sortOrder : Int = request.queryParam("sortOrder")?.let {
    json.decodeFromString(Int.serializer(), it)
  } ?: 0
  val _arg_deSelectedVerbUids : List<Long> = request.queryParam("deSelectedVerbUids")?.let {
    json.decodeFromString(ListSerializer(Long.serializer()), it)
  } ?: mutableListOf()
  val _pagingLoadParams = request.requirePagingSourceLoadParams(
    json = json,
    keyDeserializationStrategy = Int.serializer().nullable,
  )

  val _result_findStatementsBySession_pagingSource = findStatementsBySession(
    registrationHi = _arg_registrationHi,
    registrationLo = _arg_registrationLo,
    accountPersonUid = _arg_accountPersonUid,
    selectedPersonUid = _arg_selectedPersonUid,
    contentEntryUid = _arg_contentEntryUid,
    searchText = _arg_searchText,
    sortOrder = _arg_sortOrder,
    deSelectedVerbUids = _arg_deSelectedVerbUids,
  ).loadPageDataForHttp(_pagingLoadParams)
  val _result_findStatementsBySession = _result_findStatementsBySession_pagingSource.data
  serverConfig.logger.log(DoorLogLevel.VERBOSE,
      "DoorPaging: loaded from: ${_pagingLoadParams.key} endOfPaginationReached=${_result_findStatementsBySession_pagingSource.endOfPaginationReached}")
  val _endOfPaginationReached = _result_findStatementsBySession_pagingSource.endOfPaginationReached

  val _result_findActivityEntryLangMapsForStatementsBySession =
      findActivityEntryLangMapsForStatementsBySession(
    registrationHi = _arg_registrationHi,
    registrationLo = _arg_registrationLo,
  )
  val replicationEntities = buildList<DoorReplicationEntity> {
    addAll(
      _result_findStatementsBySession.map {
        _row ->
        DoorReplicationEntity(tableId = 60,
          orUid = 0,
          entity = json.encodeToJsonElement(StatementEntity.serializer(),
              _row.statementEntity).jsonObject,
        )
      }
    )
    addAll(
      _result_findStatementsBySession.mapNotNull {
        _row ->
        _row.verb?.let {
          DoorReplicationEntity(tableId = 62,
            orUid = 0,
            entity = json.encodeToJsonElement(VerbEntity.serializer(), it).jsonObject,
          )
        }

      }
    )
    addAll(
      _result_findStatementsBySession.mapNotNull {
        _row ->
        _row.verbDisplay?.let {
          DoorReplicationEntity(tableId = 620,
            orUid = 0,
            entity = json.encodeToJsonElement(VerbLangMapEntry.serializer(), it).jsonObject,
          )
        }

      }
    )
    addAll(
      _result_findStatementsBySession.mapNotNull {
        _row ->
        _row.activity?.let {
          DoorReplicationEntity(tableId = 64,
            orUid = 0,
            entity = json.encodeToJsonElement(ActivityEntity.serializer(), it).jsonObject,
          )
        }

      }
    )
    addAll(
      _result_findStatementsBySession.mapNotNull {
        _row ->
        _row.activityLangMapEntry?.let {
          DoorReplicationEntity(tableId = 6_442,
            orUid = 0,
            entity = json.encodeToJsonElement(ActivityLangMapEntry.serializer(), it).jsonObject,
          )
        }

      }
    )
    addAll(
      _result_findActivityEntryLangMapsForStatementsBySession.map {
        _row ->
        DoorReplicationEntity(tableId = 6_442,
          orUid = 0,
          entity = json.encodeToJsonElement(ActivityLangMapEntry.serializer(), _row).jsonObject,
        )
      }
    )
  }
  val _thisNodeId = request.db.doorWrapperNodeId
  return DoorJsonResponse(
    headers = buildList {
      add(Pair(DoorConstants.HEADER_NODE_ID, _thisNodeId.toString()))
      add(Pair(DoorConstants.HEADER_PAGING_END_REACHED, _endOfPaginationReached.toString()))
    }
    ,
    bodyText = json.encodeToString(
      DoorMessage.serializer(),
      DoorMessage(
        what = DoorMessage.WHAT_REPLICATION_PULL,
        fromNode = _thisNodeId,
        toNode = request.requireNodeId(),
        replications = replicationEntities,
      )
    )
  )
}

@Suppress("LocalVariableName", "RedundantSuppression", "FunctionName",
    "RedundantVisibilityModifier")
public suspend
    fun StatementDao.getUniqueVerbsForSession_DoorHttp(serverConfig: DoorHttpServerConfig,
    request: DoorJsonRequest): DoorJsonResponse {
  val json = serverConfig.json
  val _arg_registrationHi : Long = request.queryParam("registrationHi")?.let {
    json.decodeFromString(Long.serializer(), it)
  } ?: 0L
  val _arg_registrationLo : Long = request.queryParam("registrationLo")?.let {
    json.decodeFromString(Long.serializer(), it)
  } ?: 0L
  val _arg_selectedPersonUid : Long = request.queryParam("selectedPersonUid")?.let {
    json.decodeFromString(Long.serializer(), it)
  } ?: 0L
  val _arg_contentEntryUid : Long = request.queryParam("contentEntryUid")?.let {
    json.decodeFromString(Long.serializer(), it)
  } ?: 0L
  val _result_getUniqueVerbsForSession = getUniqueVerbsForSession(
    registrationHi = _arg_registrationHi,
    registrationLo = _arg_registrationLo,
    selectedPersonUid = _arg_selectedPersonUid,
    contentEntryUid = _arg_contentEntryUid,
  ).first()
  val replicationEntities = buildList<DoorReplicationEntity> {
    addAll(
      _result_getUniqueVerbsForSession.map {
        _row ->
        DoorReplicationEntity(tableId = 62,
          orUid = 0,
          entity = json.encodeToJsonElement(VerbEntity.serializer(), _row.verbEntity).jsonObject,
        )
      }
    )
    addAll(
      _result_getUniqueVerbsForSession.mapNotNull {
        _row ->
        _row.verbName?.let {
          DoorReplicationEntity(tableId = 620,
            orUid = 0,
            entity = json.encodeToJsonElement(VerbLangMapEntry.serializer(), it).jsonObject,
          )
        }

      }
    )
  }
  val _thisNodeId = request.db.doorWrapperNodeId
  return DoorJsonResponse(
    headers = buildList {
      add(Pair(DoorConstants.HEADER_NODE_ID, _thisNodeId.toString()))
    }
    ,
    bodyText = json.encodeToString(
      DoorMessage.serializer(),
      DoorMessage(
        what = DoorMessage.WHAT_REPLICATION_PULL,
        fromNode = _thisNodeId,
        toNode = request.requireNodeId(),
        replications = replicationEntities,
      )
    )
  )
}

@Suppress("LocalVariableName", "RedundantSuppression", "FunctionName",
    "RedundantVisibilityModifier")
public suspend
    fun StatementDao.scoreOrProgressDataExistsForContent_DoorHttp(serverConfig: DoorHttpServerConfig,
    request: DoorJsonRequest): DoorJsonResponse {
  val json = serverConfig.json
  val _arg_contentEntryUid : Long = request.queryParam("contentEntryUid")?.let {
    json.decodeFromString(Long.serializer(), it)
  } ?: 0L
  val _arg_accountPersonUid : Long = request.queryParam("accountPersonUid")?.let {
    json.decodeFromString(Long.serializer(), it)
  } ?: 0L
  val _result_scoreOrProgressDataExistsForContent = scoreOrProgressDataExistsForContent(
    contentEntryUid = _arg_contentEntryUid,
    accountPersonUid = _arg_accountPersonUid,
  )
  val replicationEntities = buildList<DoorReplicationEntity> {
    addAll(
      _result_scoreOrProgressDataExistsForContent.map {
        _row ->
        DoorReplicationEntity(tableId = 60,
          orUid = 0,
          entity = json.encodeToJsonElement(StatementEntity.serializer(), _row).jsonObject,
        )
      }
    )
  }
  val _thisNodeId = request.db.doorWrapperNodeId
  return DoorJsonResponse(
    headers = buildList {
      add(Pair(DoorConstants.HEADER_NODE_ID, _thisNodeId.toString()))
    }
    ,
    bodyText = json.encodeToString(
      DoorMessage.serializer(),
      DoorMessage(
        what = DoorMessage.WHAT_REPLICATION_PULL,
        fromNode = _thisNodeId,
        toNode = request.requireNodeId(),
        replications = replicationEntities,
      )
    )
  )
}
