package com.example.myapplication.api.user.repository

import com.example.myapplication.api.MyServerService
import com.example.myapplication.api.item.remote.toItemFromCart
import com.example.myapplication.api.user.remote.toUser
import com.example.myapplication.api.user.remote.toUserRemote
import com.example.myapplication.database.room.model.item.ItemFromCart
import com.example.myapplication.database.room.model.user.User
import com.example.myapplication.database.room.model.user.UserItemCrossRef
import com.example.myapplication.database.room.repository.offline.OfflineUserItemRepository
import com.example.myapplication.database.room.repository.offline.OfflineUserRepository
import com.example.myapplication.database.room.repository.online.UserRepository

class RestUserRepository(
    private val service: MyServerService,
    private val dbUserRepository: OfflineUserRepository,
    private val dbUserItemRepository: OfflineUserItemRepository,
) : UserRepository {
    override suspend fun getAllUsers(): List<User> {
        val existUsers = dbUserRepository.getAllUsers().associateBy { it.uid }.toMutableMap()

        service.getUsers()
            .map { it.toUser() }
            .forEach { user ->
                val existUser = existUsers[user.uid]
                if (existUser == null) {
                    dbUserRepository.insertUser(user)
                } else if (existUser != user) {
                    dbUserRepository.updateUser(user)
                }
                existUsers[user.uid] = user
            }

        return existUsers.map { it.value }.sortedBy { it.uid }
    }

    override suspend fun getCartByUser(userId: Int): List<ItemFromCart> {
        val cart = service.getUserCart(userId)
        dbUserItemRepository.deleteUserItems(userId)
        cart.items.map { itemFromCartRemote ->
            dbUserItemRepository.insertUserItem(
                UserItemCrossRef(
                    userId,
                    itemFromCartRemote.id,
                    itemFromCartRemote.count
                )
            )
        }

        return cart.items.map {
            val item = service.getItem(it.id)
            it.toItemFromCart(
                item.bike,
                item.dateTime,
                item.weight,
                item.radius,
                item.colorbike,
                item.maxCount - service.getRents().flatMap { rent ->
                    rent.items.filter { item -> item.id == it.id }
                }.sumOf { item -> item.count })
        }
    }

    override suspend fun insertUser(user: User) {
        service.createUser(user.toUserRemote()).toUser()
    }

    override suspend fun updateUser(user: User) {
        user.uid?.let { service.updateUser(it, user.toUserRemote()).toUser() }
    }

    override suspend fun deleteUser(user: User) {
        user.uid?.let { service.deleteUser(it).toUser() }
    }

    override suspend fun getUserById(idUser: Int?): User? =
        idUser?.let { service.getUser(it).toUser() }
}