package ch.threema.storage.factories

import android.database.sqlite.SQLiteException
import ch.threema.base.utils.getThreemaLogger
import ch.threema.storage.CursorHelper
import ch.threema.storage.DatabaseCreationProvider
import ch.threema.storage.DatabaseProvider
import ch.threema.storage.buildContentValues
import ch.threema.storage.models.ServerMessageModel
import ch.threema.storage.runDelete
import ch.threema.storage.runQuery
import java.sql.SQLException

private val logger = getThreemaLogger("ServerMessageModelFactory")

class ServerMessageModelFactory(databaseProvider: DatabaseProvider) :
    ModelFactory(databaseProvider, ServerMessageModel.TABLE) {
    fun storeServerMessageModel(serverMessageModel: ServerMessageModel) {
        val contentValues = buildContentValues {
            put(ServerMessageModel.COLUMN_MESSAGE, serverMessageModel.message)
            put(ServerMessageModel.COLUMN_TYPE, serverMessageModel.type)
        }
        try {
            writableDatabase.insertOrThrow(tableName, null, contentValues)
        } catch (e: SQLException) {
            logger.error("Could not store server message", e)
        }
    }

    fun popServerMessageModel(): ServerMessageModel? {
        val cursor = readableDatabase.runQuery(
            table = ServerMessageModel.TABLE,
            columns = arrayOf(ServerMessageModel.COLUMN_MESSAGE, ServerMessageModel.COLUMN_TYPE),
            limit = "1",
        )
        if (cursor.moveToFirst()) {
            val cursorHelper = CursorHelper(cursor, columnIndexCache)
            return convertAndDelete(cursorHelper)
        }
        return null
    }

    fun delete(message: String) {
        writableDatabase.runDelete(
            table = ServerMessageModel.TABLE,
            whereClause = "${ServerMessageModel.COLUMN_MESSAGE}=?",
            whereArgs = arrayOf(message),
        )
    }

    private fun convertAndDelete(c: CursorHelper): ServerMessageModel? {
        return try {
            val message = c.getString(ServerMessageModel.COLUMN_MESSAGE) ?: ""
            val type = c.getInt(ServerMessageModel.COLUMN_TYPE) ?: -1
            val messageModel = if (message.isNotBlank() && type >= 0) {
                ServerMessageModel(message, type)
            } else {
                logger.info("Invalid message '{}' or type '{}'", message, type)
                null
            }
            delete(message)
            messageModel
        } catch (e: SQLiteException) {
            logger.error("Could not load server message model", e)
            null
        }
    }

    object Creator : DatabaseCreationProvider {
        override fun getCreationStatements() = arrayOf(
            "CREATE TABLE `${ServerMessageModel.TABLE}` (" +
                "`${ServerMessageModel.COLUMN_MESSAGE}` VARCHAR PRIMARY KEY ON CONFLICT REPLACE," +
                "`${ServerMessageModel.COLUMN_TYPE}` INTEGER" +
                ")",
        )
    }
}
