package com.seven.ikar.kotlin.core.contacts

import com.seven.ikar.kotlin.core.model.UserSummaryDto
import com.seven.ikar.kotlin.core.network.ApiClient
import com.seven.ikar.kotlin.core.network.ServerConfig
import com.seven.ikar.kotlin.core.session.AuthorizedSessionManager
import com.seven.ikar.kotlin.core.session.SessionStore
import kotlinx.coroutines.Dispatchers
import kotlinx.coroutines.withContext

data class DiscoverUserItem(
    val user: UserSummaryDto,
    val displayName: String,
    val normalizedPhoneNumber: String,
    val isSelected: Boolean = false
) {
    val id: String get() = user.id
    val username: String get() = user.username
    val avatarUrl: String? get() = ServerConfig.normalizeMediaUrl(user.avatarPath)
    val secondaryLine: String
        get() = if (user.isBot) {
            "бот · @${user.username}"
        } else if (displayName == user.displayName) {
            ""
        } else {
            "ИКАР: ${user.displayName}"
        }
}

class ResolvedContactsRepository(
    private val apiClient: ApiClient,
    private val sessionStore: SessionStore,
    private val authorizedSessionManager: AuthorizedSessionManager,
    private val contactDiscoveryService: AndroidContactDiscoveryService
) {
    suspend fun loadResolvedContacts(): List<DiscoverUserItem> = withContext(Dispatchers.IO) {
        val contacts = contactDiscoveryService.getContacts()
        if (sessionStore.read() == null) {
            return@withContext emptyList()
        }
        val resolved = authorizedSessionManager.executeAuthorized { session ->
            apiClient.resolveContacts(
                accessToken = session.accessToken,
                phoneNumbers = contacts.map { it.normalizedPhoneNumber }.distinct()
            )
        }

        val contactMap = contacts.associateBy { it.normalizedPhoneNumber }
        return@withContext resolved
            .mapNotNull { match ->
                val deviceContact = contactMap[match.phoneNumber] ?: return@mapNotNull null
                DiscoverUserItem(
                    user = match.user,
                    displayName = deviceContact.displayName,
                    normalizedPhoneNumber = deviceContact.normalizedPhoneNumber
                )
            }
            .sortedWith(
                compareByDescending<DiscoverUserItem> { it.user.isBot }
                    .thenByDescending { it.user.isOnline }
                    .thenBy { it.displayName.lowercase() }
            )
    }

    suspend fun loadMergedCandidates(query: String): List<DiscoverUserItem> = withContext(Dispatchers.IO) {
        if (sessionStore.read() == null) {
            return@withContext emptyList()
        }
        val contacts = loadResolvedContacts()
        if (query.isBlank()) {
            return@withContext contacts
        }

        val merged = contacts.toMutableList()
        val existingIds = merged.map { it.id }.toMutableSet()
        val remoteUsers = authorizedSessionManager.executeAuthorized { session ->
            apiClient.searchUsers(session.accessToken, query)
        }
        remoteUsers.forEach { user ->
            if (existingIds.add(user.id)) {
                merged += DiscoverUserItem(
                    user = user,
                    displayName = user.displayName,
                    normalizedPhoneNumber = PhoneNumberNormalizer.normalize(user.phoneNumber) ?: ""
                )
            }
        }

        return@withContext merged.sortedWith(
            compareByDescending<DiscoverUserItem> { it.user.isBot }
                .thenByDescending { it.user.isOnline }
                .thenBy { it.displayName.lowercase() }
        )
    }
}
