package ch.threema.app.testutils

import ch.threema.app.managers.ServiceManager
import ch.threema.data.datatypes.GroupIdentity
import ch.threema.data.models.ContactModel
import ch.threema.storage.DatabaseProvider
import ch.threema.storage.runTransaction
import org.koin.mp.KoinPlatform

fun clearDatabaseAndCaches(serviceManager: ServiceManager) {
    // First get all available contacts and groups
    val contactIdentities = serviceManager.modelRepositories
        .contacts
        .getAll()
        .map(ContactModel::identity)
    val groupModelRepository = serviceManager.modelRepositories.groups
    val groups = serviceManager.databaseService.groupModelFactory.all
        .map { group ->
            GroupIdentity(group.creatorIdentity, group.apiGroupId.toLong())
        }.onEach {
            // Because the column id is lazily loaded, we need to access it at least once
            // before the group model is deleted below
            groupModelRepository.getByGroupIdentity(it)?.getDatabaseId()
        }

    // Clear entire database
    KoinPlatform.getKoin().get<DatabaseProvider>().writableDatabase.runTransaction {
        rawExecSQL("PRAGMA foreign_keys = OFF;")

        query("SELECT name FROM sqlite_schema WHERE type = 'table' AND name NOT LIKE 'sqlite_%'").use { cursor ->
            while (cursor.moveToNext()) {
                rawExecSQL("DELETE FROM ${cursor.getString(0)};")
            }
        }

        rawExecSQL("PRAGMA foreign_keys = ON;")
    }

    // Clear caches in services and trigger listeners to refresh the new models from database
    val contactService = serviceManager.contactService
    val myIdentity = serviceManager.identityStore.getIdentityString()
    contactIdentities.forEach { identity ->
        contactService.invalidateCache(identity)
        serviceManager.dhSessionStore.deleteAllDHSessions(myIdentity, identity)
    }
    val groupService = serviceManager.groupService
    groupService.removeAll()
    groups.forEach { groupIdentity ->
        groupService.removeFromCache(groupIdentity)
        groupModelRepository.persistRemovedGroup(groupIdentity)
    }
    serviceManager.conversationService.reset()
}
