package com.ustadmobile.core.db.dao

import androidx.paging.PagingSource
import com.ustadmobile.door.DoorDatabaseRepository
import com.ustadmobile.door.DoorQuery
import com.ustadmobile.door.ext.doorNodeIdHeader
import com.ustadmobile.door.ext.pagingSourceLoadParameters
import com.ustadmobile.door.ext.setRepoUrl
import com.ustadmobile.door.http.replicateHttpRequestCatchAndLog
import com.ustadmobile.door.http.replicateHttpRequestOrThrow
import com.ustadmobile.door.http.repoHttpRequestWithFallback
import com.ustadmobile.door.paging.DoorRepositoryReplicatePullPagingSource
import com.ustadmobile.door.paging.endOfPaginationReached
import com.ustadmobile.door.replication.onClientRepoDoorMessageHttpResponse
import com.ustadmobile.door.replication.withRepoChangeMonitor
import com.ustadmobile.door.replication.withRepoChangeMonitorAsync
import com.ustadmobile.door.room.RoomDatabase
import com.ustadmobile.lib.db.entities.Report
import io.ktor.client.HttpClient
import io.ktor.client.request.`get`
import io.ktor.client.request.`header`
import io.ktor.client.request.parameter
import io.ktor.client.statement.bodyAsText
import kotlin.Boolean
import kotlin.Int
import kotlin.Long
import kotlin.String
import kotlin.Suppress
import kotlin.Unit
import kotlin.collections.List
import kotlinx.coroutines.flow.Flow
import kotlinx.serialization.builtins.nullable
import kotlinx.serialization.builtins.serializer

@Suppress("REDUNDANT_PROJECTION", "LocalVariableName", "ClassName")
public class ReportDao_Repo(
  public val _db: RoomDatabase,
  public val _repo: DoorDatabaseRepository,
  public val _dao: ReportDao,
  public val _httpClient: HttpClient,
  public val _clientId: Long,
  public val _endpoint: String,
) : ReportDao() {
  override fun getResults(query: DoorQuery): List<Report> {
    val _result = _dao.getResults(query)
    return _result
  }

  override suspend fun deleteReportByUid(reportUid: Long) {
    _repo.repoHttpRequestWithFallback(
      repoPath = "ReportDao/deleteReportByUid",
      http =  {
        _repo.config.json.decodeFromString(
          deserializer = Unit.serializer(),
          string = _repo.config.httpClient.`get` {
            setRepoUrl(_repo.config, "ReportDao/deleteReportByUid")
            doorNodeIdHeader(_repo)
            `header`("cache-control", "no-store")
            parameter("reportUid", _repo.config.json.encodeToString(Long.serializer(), reportUid))
          }
          .bodyAsText()
        )
      } ,
      fallback =  {
        _dao.deleteReportByUid(reportUid)
      }

    )
  }

  override fun findAllReports(): PagingSource<Int, Report> =
      DoorRepositoryReplicatePullPagingSource(
    repo = _repo,
    repoPath = "ReportDao/findAllReports",
    dbPagingSource = _dao.findAllReports(),
    onLoadHttp =  {
      _pagingParams -> 
      _repo.replicateHttpRequestOrThrow(repoPath = "ReportDao/findAllReports") {
        val _response = _httpClient.`get` {
          setRepoUrl(_repo.config, "ReportDao/findAllReports")
          doorNodeIdHeader(_repo)
          `header`("cache-control", "no-store")
          pagingSourceLoadParameters(
            json = _repo.config.json, 
            keySerializer = Int.serializer().nullable,
            loadParams = _pagingParams
          )
        }

        _db.onClientRepoDoorMessageHttpResponse(_response, _repo.config.json)
        _response.endOfPaginationReached()
      }
    },
  )

  override fun findAllActiveReport(searchBit: String, isTemplate: Boolean):
      PagingSource<Int, Report> {
    val _result = _dao.findAllActiveReport(searchBit, isTemplate)
    return _result
  }

  override suspend fun findByUid(entityUid: Long): Report? {
    _repo.replicateHttpRequestCatchAndLog(repoPath = "ReportDao/findByUid") {
      val _response = _httpClient.`get` {
        setRepoUrl(_repo.config, "ReportDao/findByUid")
        doorNodeIdHeader(_repo)
        `header`("cache-control", "no-store")
        parameter("entityUid", _repo.config.json.encodeToString(Long.serializer(), entityUid))
      }

      _db.onClientRepoDoorMessageHttpResponse(_response, _repo.config.json)
    }
    val _result = _dao.findByUid(entityUid)
    return _result
  }

  override suspend fun updateAsync(entity: Report) {
    _repo.withRepoChangeMonitorAsync("Report") {
      _dao.updateAsync(entity)
    }
  }

  override fun findByUidLive(uid: Long): Flow<Report?> {
    val _result = _dao.findByUidLive(uid)
    return _result
  }

  override fun findAllActiveReportLive(isTemplate: Boolean): Flow<List<Report>> {
    val _result = _dao.findAllActiveReportLive(isTemplate)
    return _result
  }

  override fun findAllActiveReportList(isTemplate: Boolean): List<Report> {
    val _result = _dao.findAllActiveReportList(isTemplate)
    return _result
  }

  override fun findByUidList(uidList: List<Long>): List<Long> {
    val _result = _dao.findByUidList(uidList)
    return _result
  }

  override suspend fun toggleVisibilityReportItems(
    toggleVisibility: Boolean,
    selectedItem: List<Long>,
    updateTime: Long,
  ) {
    _repo.withRepoChangeMonitorAsync("Report") {
      _dao.toggleVisibilityReportItems(toggleVisibility, selectedItem, updateTime)
    }
  }

  override fun replaceList(entityList: List<Report>) {
    _repo.withRepoChangeMonitor("Report") {
      _dao.replaceList(entityList)
    }
  }

  public override fun insert(entity: Report): Long {
    val _result = _repo.withRepoChangeMonitor("Report") {
      _dao.insert(entity)
    }
    return _result
  }

  public override suspend fun insertAsync(entity: Report): Long {
    val _result = _repo.withRepoChangeMonitorAsync("Report") {
      _dao.insertAsync(entity)
    }
    return _result
  }

  public override fun insertList(entityList: List<Report>) {
    _repo.withRepoChangeMonitor("Report") {
      _dao.insertList(entityList)
    }
  }

  public override fun update(entity: Report) {
    _repo.withRepoChangeMonitor("Report") {
      _dao.update(entity)
    }
  }
}
