package de.krisenvorrat.server.repository

import de.krisenvorrat.server.db.Inventories
import de.krisenvorrat.server.db.Users
import de.krisenvorrat.server.model.UserDto
import org.jetbrains.exposed.sql.SqlExpressionBuilder.eq
import org.jetbrains.exposed.sql.deleteWhere
import org.jetbrains.exposed.sql.insert
import org.jetbrains.exposed.sql.selectAll
import org.jetbrains.exposed.sql.transactions.transaction
import org.jetbrains.exposed.sql.update
import java.util.UUID

internal data class UserRow(
    val id: String,
    val username: String,
    val passwordHash: String,
    val createdAt: Long,
    val isAdmin: Boolean,
    val inventoryId: String? = null
)

internal class UserRepository {

    fun create(id: String, username: String, passwordHash: String, isAdmin: Boolean = false): Boolean {
        return transaction {
            val inventoryId = UUID.randomUUID().toString()
            Inventories.insert {
                it[Inventories.id] = inventoryId
                it[Inventories.createdAt] = System.currentTimeMillis()
            }
            val inserted = Users.insert {
                it[Users.id] = id
                it[Users.username] = username
                it[Users.passwordHash] = passwordHash
                it[Users.createdAt] = System.currentTimeMillis()
                it[Users.isAdmin] = isAdmin
                it[Users.inventoryId] = inventoryId
            }.insertedCount
            inserted > 0
        }
    }

    fun findByUsername(username: String): UserRow? = transaction {
        Users.selectAll()
            .where { Users.username eq username }
            .map { it.toUserRow() }
            .singleOrNull()
    }

    fun findById(id: String): UserRow? = transaction {
        Users.selectAll()
            .where { Users.id eq id }
            .map { it.toUserRow() }
            .singleOrNull()
    }

    fun listAll(): List<UserDto> = transaction {
        Users.selectAll().map {
            UserDto(
                id = it[Users.id],
                username = it[Users.username],
                createdAt = it[Users.createdAt],
                isAdmin = it[Users.isAdmin],
                inventoryId = it[Users.inventoryId]
            )
        }
    }

    fun deleteById(id: String): Boolean = transaction {
        Users.deleteWhere { Users.id eq id } > 0
    }

    fun updatePassword(id: String, passwordHash: String): Boolean = transaction {
        Users.update({ Users.id eq id }) {
            it[Users.passwordHash] = passwordHash
        } > 0
    }

    fun count(): Long = transaction { Users.selectAll().count() }

    private fun org.jetbrains.exposed.sql.ResultRow.toUserRow() = UserRow(
        id = this[Users.id],
        username = this[Users.username],
        passwordHash = this[Users.passwordHash],
        createdAt = this[Users.createdAt],
        isAdmin = this[Users.isAdmin],
        inventoryId = this[Users.inventoryId]
    )
}

