package de.trainingstagebuch.app.viewmodel

import android.app.Application
import androidx.lifecycle.AndroidViewModel
import androidx.lifecycle.viewModelScope
import de.trainingstagebuch.app.R
import de.trainingstagebuch.app.repository.MemberTransferActionResult
import de.trainingstagebuch.app.repository.MemberTransferConfig
import de.trainingstagebuch.app.repository.MemberTransferConfigInput
import de.trainingstagebuch.app.repository.MemberTransferConfigResult
import de.trainingstagebuch.app.repository.MemberTransferExecutionResult
import de.trainingstagebuch.app.repository.MemberTransferSummary
import de.trainingstagebuch.app.services.AppServices
import de.trainingstagebuch.app.utils.UiText
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch

class MemberTransferSettingsViewModel(application: Application) : AndroidViewModel(application) {

    private val authService = AppServices.authService
    private val memberTransferService = AppServices.memberTransferService

    private val _state = MutableStateFlow(MemberTransferUiState())
    val state: StateFlow<MemberTransferUiState> = _state.asStateFlow()

    init {
        loadConfig()
    }

    fun onServerChanged(value: String) = _state.update { it.copy(server = value) }
    fun onLoginEndpointChanged(value: String) = _state.update { it.copy(loginEndpoint = value) }
    fun onLoginFormatChanged(value: String) = _state.update { it.copy(loginFormat = value) }
    fun onLoginUsernameChanged(value: String) = _state.update { it.copy(loginUsername = value) }
    fun onLoginPasswordChanged(value: String) = _state.update { it.copy(loginPassword = value) }
    fun onLoginAdditionalField1Changed(value: String) = _state.update { it.copy(loginAdditionalField1 = value) }
    fun onLoginAdditionalField2Changed(value: String) = _state.update { it.copy(loginAdditionalField2 = value) }
    fun onTransferEndpointChanged(value: String) = _state.update { it.copy(transferEndpoint = value) }
    fun onTransferMethodChanged(value: String) = _state.update { it.copy(transferMethod = value) }
    fun onTransferFormatChanged(value: String) = _state.update { it.copy(transferFormat = value) }
    fun onTransferTemplateChanged(value: String) = _state.update { it.copy(transferTemplate = value) }
    fun onUseBulkModeChanged(value: Boolean) = _state.update { it.copy(useBulkMode = value) }
    fun onBulkWrapperTemplateChanged(value: String) = _state.update { it.copy(bulkWrapperTemplate = value) }

    fun loadConfig() {
        viewModelScope.launch {
            val clubId = resolveClubId() ?: return@launch
            _state.update { it.copy(loading = true, message = null) }
            when (val result = memberTransferService.loadConfig(clubId)) {
                is MemberTransferConfigResult.Success -> {
                    val config = result.config
                    _state.update {
                        if (config == null) {
                            it.copy(loading = false, configId = null)
                        } else {
                            it.withConfig(config).copy(loading = false)
                        }
                    }
                }

                is MemberTransferConfigResult.Error -> {
                    _state.update {
                        it.copy(
                            loading = false,
                            message = UiText(R.string.error_dynamic, args = listOf(result.message))
                        )
                    }
                }
            }
        }
    }

    fun saveConfig() {
        viewModelScope.launch {
            val clubId = resolveClubId() ?: return@launch
            val current = _state.value
            if (current.server.trim().isBlank() || current.transferEndpoint.trim().isBlank() || current.transferTemplate.trim().isBlank()) {
                _state.update { it.copy(message = UiText(R.string.error_required_transfer_fields)) }
                return@launch
            }

            _state.update { it.copy(saving = true, message = null) }
            when (val result = memberTransferService.saveConfig(clubId, current.toInput())) {
                is MemberTransferActionResult.Success -> {
                    _state.update {
                        it.copy(
                            saving = false,
                            configId = result.configId ?: it.configId,
                            loginPassword = "",
                            message = UiText(
                                R.string.message_dynamic,
                                args = listOf(result.message?.ifBlank { getApplication<Application>().getString(R.string.member_transfer_saved_default) }
                                    ?: getApplication<Application>().getString(R.string.member_transfer_saved_default))
                            )
                        )
                    }
                }

                is MemberTransferActionResult.Error -> {
                    _state.update {
                        it.copy(
                            saving = false,
                            message = UiText(R.string.error_dynamic, args = listOf(result.message))
                        )
                    }
                }
            }
        }
    }

    fun deleteConfig() {
        viewModelScope.launch {
            val clubId = resolveClubId() ?: return@launch
            _state.update { it.copy(deleting = true, message = null) }
            when (val result = memberTransferService.deleteConfig(clubId)) {
                is MemberTransferActionResult.Success -> {
                    _state.update {
                        MemberTransferUiState(
                            deleting = false,
                            message = UiText(
                                R.string.message_dynamic,
                                args = listOf(result.message ?: getApplication<Application>().getString(R.string.member_transfer_deleted_default))
                            )
                        )
                    }
                }

                is MemberTransferActionResult.Error -> {
                    _state.update {
                        it.copy(
                            deleting = false,
                            message = UiText(R.string.error_dynamic, args = listOf(result.message))
                        )
                    }
                }
            }
        }
    }

    fun executeTransfer() {
        viewModelScope.launch {
            val clubId = resolveClubId() ?: return@launch
            val current = _state.value
            if (current.transferEndpoint.trim().isBlank() || current.transferTemplate.trim().isBlank()) {
                _state.update { it.copy(message = UiText(R.string.error_required_transfer_fields)) }
                return@launch
            }
            _state.update { it.copy(transferring = true, message = null) }
            when (val result = memberTransferService.executeTransfer(clubId, current.toInput())) {
                is MemberTransferExecutionResult.Success -> {
                    _state.update {
                        it.copy(
                            transferring = false,
                            transferSummary = result.summary,
                            message = UiText(R.string.member_transfer_execute_success)
                        )
                    }
                }

                is MemberTransferExecutionResult.Error -> {
                    _state.update {
                        it.copy(
                            transferring = false,
                            transferSummary = result.summary,
                            message = UiText(R.string.error_dynamic, args = listOf(result.message))
                        )
                    }
                }
            }
        }
    }

    private suspend fun resolveClubId(): String? {
        val clubId = authService.session.first().currentClub?.trim().orEmpty()
        if (clubId.isBlank()) {
            _state.update { it.copy(message = UiText(R.string.error_no_current_club)) }
            return null
        }
        return clubId
    }

    private fun MemberTransferUiState.toInput(): MemberTransferConfigInput {
        return MemberTransferConfigInput(
            server = server.trim(),
            loginEndpoint = loginEndpoint.trim().ifBlank { null },
            loginFormat = loginFormat,
            loginCredentials = buildLoginCredentialsMap(
                username = loginUsername.trim(),
                password = loginPassword.trim(),
                additionalField1 = loginAdditionalField1.trim(),
                additionalField2 = loginAdditionalField2.trim()
            ),
            transferEndpoint = transferEndpoint.trim(),
            transferMethod = transferMethod,
            transferFormat = transferFormat,
            transferTemplate = transferTemplate,
            useBulkMode = useBulkMode,
            bulkWrapperTemplate = bulkWrapperTemplate.trim().ifBlank { null }
        )
    }

    private fun MemberTransferUiState.withConfig(config: MemberTransferConfig): MemberTransferUiState {
        return copy(
            configId = config.id,
            server = config.server,
            loginEndpoint = config.loginEndpoint.orEmpty(),
            loginFormat = config.loginFormat,
            loginUsername = config.loginUsername.orEmpty(),
            loginPassword = "",
            loginAdditionalField1 = config.loginAdditionalField1.orEmpty(),
            loginAdditionalField2 = config.loginAdditionalField2.orEmpty(),
            transferEndpoint = config.transferEndpoint,
            transferMethod = config.transferMethod,
            transferFormat = config.transferFormat,
            transferTemplate = config.transferTemplate,
            useBulkMode = config.useBulkMode,
            bulkWrapperTemplate = config.bulkWrapperTemplate.orEmpty()
        )
    }

    private fun buildLoginCredentialsMap(
        username: String,
        password: String,
        additionalField1: String,
        additionalField2: String
    ): Map<String, String>? {
        val result = linkedMapOf<String, String>()
        if (username.isNotBlank()) result["username"] = username
        if (password.isNotBlank()) result["password"] = password
        parseAdditionalField(additionalField1)?.let { (k, v) -> result[k] = v }
        parseAdditionalField(additionalField2)?.let { (k, v) -> result[k] = v }
        return result.takeIf { it.isNotEmpty() }
    }

    private fun parseAdditionalField(raw: String): Pair<String, String>? {
        if (raw.isBlank()) return null
        val parts = raw.split(":", limit = 2).map { it.trim() }
        val key = parts[0]
        if (key.isBlank()) return null
        val value = if (parts.size > 1) parts[1] else key
        return key to value
    }
}

data class MemberTransferUiState(
    val loading: Boolean = false,
    val saving: Boolean = false,
    val deleting: Boolean = false,
    val transferring: Boolean = false,
    val configId: String? = null,
    val server: String = "",
    val loginEndpoint: String = "",
    val loginFormat: String = "json",
    val loginUsername: String = "",
    val loginPassword: String = "",
    val loginAdditionalField1: String = "",
    val loginAdditionalField2: String = "",
    val transferEndpoint: String = "",
    val transferMethod: String = "POST",
    val transferFormat: String = "json",
    val transferTemplate: String = "",
    val useBulkMode: Boolean = false,
    val bulkWrapperTemplate: String = "",
    val transferSummary: MemberTransferSummary? = null,
    val message: UiText? = null
)
