package com.ustadmobile.core.db.dao

import com.ustadmobile.door.DoorConstants
import com.ustadmobile.door.ext.doorWrapper
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.ClazzEnrolment
import com.ustadmobile.lib.db.entities.CoursePermission
import com.ustadmobile.lib.db.entities.Person
import com.ustadmobile.lib.db.entities.PersonParentJoin
import com.ustadmobile.lib.db.entities.PersonPicture
import com.ustadmobile.lib.db.entities.SystemPermission
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 PersonDao.countUsername_DoorHttp(serverConfig: DoorHttpServerConfig,
    request: DoorJsonRequest): DoorJsonResponse {
  val json = serverConfig.json
  val _arg_username : String = request.queryParam("username")?.let {
    json.decodeFromString(String.serializer(), it)
  } ?: ""
  val _thisNodeId = request.db.doorWrapperNodeId
  val _result = countUsername(_arg_username,)
  return DoorJsonResponse(
    bodyText = json.encodeToString(Int.serializer(), _result),
    headers = listOf(DoorConstants.HEADER_NODE_ID to _thisNodeId.toString()),
  )
}

@Suppress("LocalVariableName", "RedundantSuppression", "FunctionName",
    "RedundantVisibilityModifier")
public suspend fun PersonDao.findByUidWithPicture_DoorHttp(serverConfig: DoorHttpServerConfig,
    request: DoorJsonRequest): DoorJsonResponse {
  val json = serverConfig.json
  val _arg_accountPersonUid : Long = request.queryParam("accountPersonUid")?.let {
    json.decodeFromString(Long.serializer(), it)
  } ?: 0L
  val _result_findByUidWithPicture = findByUidWithPicture(
    accountPersonUid = _arg_accountPersonUid,
  )
  val replicationEntities = buildList<DoorReplicationEntity> {
    _result_findByUidWithPicture?.person?.also {
      _row -> 
      add(
        DoorReplicationEntity(tableId = 9,
          orUid = 0,
          entity = json.encodeToJsonElement(Person.serializer(), _row).jsonObject,
        )
      )
    }
    _result_findByUidWithPicture?.picture?.also {
      _row -> 
      add(
        DoorReplicationEntity(tableId = 50,
          orUid = 0,
          entity = json.encodeToJsonElement(PersonPicture.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 PersonDao.findByUidAsync_DoorHttp(serverConfig: DoorHttpServerConfig,
    request: DoorJsonRequest): DoorJsonResponse {
  val json = serverConfig.json
  val _arg_uid : Long = request.queryParam("uid")?.let {
    json.decodeFromString(Long.serializer(), it)
  } ?: 0L
  val _result_findByUidAsync = findByUidAsync(
    uid = _arg_uid,
  )
  val replicationEntities = buildList<DoorReplicationEntity> {
    _result_findByUidAsync?.also {
      _row -> 
      add(
        DoorReplicationEntity(tableId = 9,
          orUid = 0,
          entity = json.encodeToJsonElement(Person.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 PersonDao.findPersonsWithPermissionAsPagingSource_DoorHttp(serverConfig: DoorHttpServerConfig,
    request: DoorJsonRequest): DoorJsonResponse {
  val json = serverConfig.json
  val _arg_timestamp : Long = request.queryParam("timestamp")?.let {
    json.decodeFromString(Long.serializer(), it)
  } ?: 0L
  val _arg_excludeClazz : Long = request.queryParam("excludeClazz")?.let {
    json.decodeFromString(Long.serializer(), it)
  } ?: 0L
  val _arg_excludeSelected : List<Long> = request.queryParam("excludeSelected")?.let {
    json.decodeFromString(ListSerializer(Long.serializer()), it)
  } ?: mutableListOf()
  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 _arg_searchText : String? = request.queryParam("searchText")?.let {
    json.decodeFromString(String.serializer().nullable, it)
  }
  val _pagingLoadParams = request.requirePagingSourceLoadParams(
    json = json,
    keyDeserializationStrategy = Int.serializer().nullable,
  )

  val _result_findPersonsWithPermissionAsPagingSource_pagingSource =
      findPersonsWithPermissionAsPagingSource(
    timestamp = _arg_timestamp,
    excludeClazz = _arg_excludeClazz,
    excludeSelected = _arg_excludeSelected,
    accountPersonUid = _arg_accountPersonUid,
    sortOrder = _arg_sortOrder,
    searchText = _arg_searchText,
  ).loadPageDataForHttp(_pagingLoadParams)
  val _result_findPersonsWithPermissionAsPagingSource =
      _result_findPersonsWithPermissionAsPagingSource_pagingSource.data
  serverConfig.logger.log(DoorLogLevel.VERBOSE,
      "DoorPaging: loaded from: ${_pagingLoadParams.key} endOfPaginationReached=${_result_findPersonsWithPermissionAsPagingSource_pagingSource.endOfPaginationReached}")
  val _endOfPaginationReached =
      _result_findPersonsWithPermissionAsPagingSource_pagingSource.endOfPaginationReached

  val _result_findAllByPersonUid =
      request.db.doorWrapper.getDaoByClass(SystemPermissionDao::class).findAllByPersonUid(
    accountPersonUid = _arg_accountPersonUid,
    includeDeleted = true,
  )
  val _result_findApplicableCoursePermissionEntitiesForAccountPerson =
      request.db.doorWrapper.getDaoByClass(CoursePermissionDao::class).findApplicableCoursePermissionEntitiesForAccountPerson(
    accountPersonUid = _arg_accountPersonUid,
  )
  val _result_findClazzEnrolmentEntitiesForPersonViewPermissionCheck =
      request.db.doorWrapper.getDaoByClass(ClazzEnrolmentDao::class).findClazzEnrolmentEntitiesForPersonViewPermissionCheck(
    accountPersonUid = _arg_accountPersonUid,
    otherPersonUid = 0,
  )
  val replicationEntities = buildList<DoorReplicationEntity> {
    addAll(
      _result_findPersonsWithPermissionAsPagingSource.mapNotNull {
        _row ->
        _row.person?.let {
          DoorReplicationEntity(tableId = 9,
            orUid = 0,
            entity = json.encodeToJsonElement(Person.serializer(), it).jsonObject,
          )
        }

      }
    )
    addAll(
      _result_findPersonsWithPermissionAsPagingSource.mapNotNull {
        _row ->
        _row.picture?.let {
          DoorReplicationEntity(tableId = 50,
            orUid = 0,
            entity = json.encodeToJsonElement(PersonPicture.serializer(), it).jsonObject,
          )
        }

      }
    )
    addAll(
      _result_findAllByPersonUid.map {
        _row ->
        DoorReplicationEntity(tableId = 10_011,
          orUid = 0,
          entity = json.encodeToJsonElement(SystemPermission.serializer(), _row).jsonObject,
        )
      }
    )
    addAll(
      _result_findApplicableCoursePermissionEntitiesForAccountPerson.map {
        _row ->
        DoorReplicationEntity(tableId = 10_012,
          orUid = 0,
          entity = json.encodeToJsonElement(CoursePermission.serializer(), _row).jsonObject,
        )
      }
    )
    addAll(
      _result_findClazzEnrolmentEntitiesForPersonViewPermissionCheck.map {
        _row ->
        DoorReplicationEntity(tableId = 65,
          orUid = 0,
          entity = json.encodeToJsonElement(ClazzEnrolment.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 PersonDao.findByUidWithDisplayDetailsFlow_DoorHttp(serverConfig: DoorHttpServerConfig,
    request: DoorJsonRequest): DoorJsonResponse {
  val json = serverConfig.json
  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 _result_findByUidWithDisplayDetailsFlow = findByUidWithDisplayDetailsFlow(
    personUid = _arg_personUid,
    accountPersonUid = _arg_accountPersonUid,
  ).first()
  val replicationEntities = buildList<DoorReplicationEntity> {
    _result_findByUidWithDisplayDetailsFlow?.person?.also {
      _row -> 
      add(
        DoorReplicationEntity(tableId = 9,
          orUid = 0,
          entity = json.encodeToJsonElement(Person.serializer(), _row).jsonObject,
        )
      )
    }
    _result_findByUidWithDisplayDetailsFlow?.parentJoin?.also {
      _row -> 
      add(
        DoorReplicationEntity(tableId = 512,
          orUid = 0,
          entity = json.encodeToJsonElement(PersonParentJoin.serializer(), _row).jsonObject,
        )
      )
    }
    _result_findByUidWithDisplayDetailsFlow?.personPicture?.also {
      _row -> 
      add(
        DoorReplicationEntity(tableId = 50,
          orUid = 0,
          entity = json.encodeToJsonElement(PersonPicture.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 PersonDao.getNamesByUid_DoorHttp(serverConfig: DoorHttpServerConfig,
    request: DoorJsonRequest): DoorJsonResponse {
  val json = serverConfig.json
  val _arg_uid : Long = request.queryParam("uid")?.let {
    json.decodeFromString(Long.serializer(), it)
  } ?: 0L
  val _result_findByUidAsync = findByUidAsync(
    uid = _arg_uid,
  )
  val replicationEntities = buildList<DoorReplicationEntity> {
    _result_findByUidAsync?.also {
      _row -> 
      add(
        DoorReplicationEntity(tableId = 9,
          orUid = 0,
          entity = json.encodeToJsonElement(Person.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 PersonDao.getNamesByUidAsync_DoorHttp(serverConfig: DoorHttpServerConfig,
    request: DoorJsonRequest): DoorJsonResponse {
  val json = serverConfig.json
  val _arg_uid : Long = request.queryParam("uid")?.let {
    json.decodeFromString(Long.serializer(), it)
  } ?: 0L
  val _result_findByUidAsync = findByUidAsync(
    uid = _arg_uid,
  )
  val replicationEntities = buildList<DoorReplicationEntity> {
    _result_findByUidAsync?.also {
      _row -> 
      add(
        DoorReplicationEntity(tableId = 9,
          orUid = 0,
          entity = json.encodeToJsonElement(Person.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,
      )
    )
  )
}
