package com.seven.ikar.kotlin.feature.privacy

import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.seven.ikar.kotlin.app.AppContainer
import com.seven.ikar.kotlin.core.model.PrivacySettingsDto
import com.seven.ikar.kotlin.core.model.UpdatePrivacySettingsRequest
import com.seven.ikar.kotlin.core.model.UserSummaryDto
import kotlinx.coroutines.Job
import kotlinx.coroutines.delay
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch

data class PrivacySecurityUiState(
    val settings: PrivacySettingsDto? = null,
    val userSearchQuery: String = "",
    val userSearchResults: List<UserSummaryDto> = emptyList(),
    val isSearchingUsers: Boolean = false,
    val isLoading: Boolean = false,
    val isSaving: Boolean = false,
    val errorMessage: String? = null
)

class PrivacySecurityViewModel(private val container: AppContainer) : ViewModel() {
    private val _uiState = MutableStateFlow(PrivacySecurityUiState())
    private var userSearchJob: Job? = null
    val uiState: StateFlow<PrivacySecurityUiState> = _uiState.asStateFlow()

    init {
        refresh()
    }

    fun refresh() {
        viewModelScope.launch {
            _uiState.value = _uiState.value.copy(isLoading = true, errorMessage = null)
            runCatching {
                container.executeAuthorized { session ->
                    container.apiClient.getMyPrivacySettings(session.accessToken)
                }
            }.onSuccess { settings ->
                container.privacyRuntimeSettings.saveFrom(settings)
                _uiState.value = _uiState.value.copy(settings = settings, isLoading = false)
            }.onFailure { error ->
                _uiState.value = _uiState.value.copy(isLoading = false, errorMessage = error.message)
            }
        }
    }

    fun update(transform: (PrivacySettingsDto) -> PrivacySettingsDto) {
        val current = _uiState.value.settings ?: return
        val next = transform(current)
        saveSettings(current, next)
    }

    fun updateUserSearchQuery(value: String) {
        _uiState.value = _uiState.value.copy(userSearchQuery = value)
        userSearchJob?.cancel()
        userSearchJob = viewModelScope.launch {
            delay(250)
            searchUsers(value)
        }
    }

    fun blockUser(user: UserSummaryDto) {
        update { settings ->
            settings.copy(
                blockedUserIds = (settings.blockedUserIds + user.id).distinct(),
                alwaysAllowUserIds = settings.alwaysAllowUserIds - user.id
            )
        }
    }

    fun unblockUser(userId: String) {
        update { settings -> settings.copy(blockedUserIds = settings.blockedUserIds - userId) }
    }

    fun alwaysAllowUser(user: UserSummaryDto) {
        update { settings ->
            settings.copy(
                alwaysAllowUserIds = (settings.alwaysAllowUserIds + user.id).distinct(),
                neverAllowUserIds = settings.neverAllowUserIds - user.id,
                blockedUserIds = settings.blockedUserIds - user.id
            )
        }
    }

    fun neverAllowUser(user: UserSummaryDto) {
        update { settings ->
            settings.copy(
                neverAllowUserIds = (settings.neverAllowUserIds + user.id).distinct(),
                alwaysAllowUserIds = settings.alwaysAllowUserIds - user.id
            )
        }
    }

    fun removeAlwaysAllow(userId: String) {
        update { settings -> settings.copy(alwaysAllowUserIds = settings.alwaysAllowUserIds - userId) }
    }

    fun removeNeverAllow(userId: String) {
        update { settings -> settings.copy(neverAllowUserIds = settings.neverAllowUserIds - userId) }
    }

    fun enablePasscode(passcode: String, confirmation: String) {
        val current = _uiState.value.settings ?: return
        val normalized = passcode.trim()
        if (!isValidPasscode(normalized)) {
            _uiState.value = _uiState.value.copy(errorMessage = "Код должен содержать 4-12 цифр.")
            return
        }
        if (normalized != confirmation.trim()) {
            _uiState.value = _uiState.value.copy(errorMessage = "Коды не совпадают.")
            return
        }

        saveSettings(
            current = current,
            next = current.copy(passcodeLockEnabled = true),
            afterSuccess = { container.privacyRuntimeSettings.setPasscode(normalized) }
        )
    }

    fun disablePasscode(passcode: String) {
        val current = _uiState.value.settings ?: return
        val normalized = passcode.trim()
        if (container.privacyRuntimeSettings.hasPasscode() &&
            !container.privacyRuntimeSettings.verifyPasscode(normalized)
        ) {
            _uiState.value = _uiState.value.copy(errorMessage = "Неверный код.")
            return
        }

        saveSettings(
            current = current,
            next = current.copy(passcodeLockEnabled = false),
            afterSuccess = { container.privacyRuntimeSettings.clearPasscode() }
        )
    }

    private fun saveSettings(
        current: PrivacySettingsDto,
        next: PrivacySettingsDto,
        afterSuccess: () -> Unit = {}
    ) {
        viewModelScope.launch {
            _uiState.value = _uiState.value.copy(settings = next, isSaving = true, errorMessage = null)
            runCatching {
                container.executeAuthorized { session ->
                    container.apiClient.updateMyPrivacySettings(
                        session.accessToken,
                        UpdatePrivacySettingsRequest(
                            phoneNumberVisibility = next.phoneNumberVisibility,
                            lastSeenVisibility = next.lastSeenVisibility,
                            profilePhotoVisibility = next.profilePhotoVisibility,
                            blockedUserIds = next.blockedUserIds,
                            alwaysAllowUserIds = next.alwaysAllowUserIds,
                            neverAllowUserIds = next.neverAllowUserIds,
                            passcodeLockEnabled = next.passcodeLockEnabled,
                            showMessagePreview = next.showMessagePreview
                        )
                    )
                }
            }.onSuccess { saved ->
                afterSuccess()
                container.privacyRuntimeSettings.saveFrom(saved)
                _uiState.value = _uiState.value.copy(settings = saved, isSaving = false)
            }.onFailure { error ->
                _uiState.value = _uiState.value.copy(settings = current, isSaving = false, errorMessage = error.message)
            }
        }
    }

    private fun isValidPasscode(value: String): Boolean =
        value.length in 4..12 && value.all { it.isDigit() }

    private suspend fun searchUsers(query: String) {
        val normalizedQuery = query.trim()
        if (normalizedQuery.length < 2) {
            _uiState.value = _uiState.value.copy(userSearchResults = emptyList(), isSearchingUsers = false)
            return
        }

        _uiState.value = _uiState.value.copy(isSearchingUsers = true)
        runCatching {
            container.executeAuthorized { session ->
                container.apiClient.searchUsers(session.accessToken, normalizedQuery)
            }
        }.onSuccess { users ->
            _uiState.value = _uiState.value.copy(userSearchResults = users, isSearchingUsers = false)
        }.onFailure { error ->
            _uiState.value = _uiState.value.copy(isSearchingUsers = false, errorMessage = error.message)
        }
    }
}

internal fun nextVisibility(value: String): String = when (value) {
    "everyone" -> "contacts"
    "contacts" -> "nobody"
    else -> "everyone"
}
