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.LogDetailItem
import de.trainingstagebuch.app.repository.LogDetailResult
import de.trainingstagebuch.app.repository.LogItem
import de.trainingstagebuch.app.repository.LogsResult
import de.trainingstagebuch.app.services.AppServices
import de.trainingstagebuch.app.utils.UiText
import de.trainingstagebuch.app.utils.ViewModelStateUtils
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch

data class LogsFilters(
    val backend: String = "",
    val logType: String = "",
    val method: String = "",
    val statusCode: String = "",
    val path: String = "",
    val startDate: String = "",
    val endDate: String = ""
)

data class LogsUiState(
    val loading: Boolean = false,
    val loadingDetail: Boolean = false,
    val logs: List<LogItem> = emptyList(),
    val total: Int = 0,
    val limit: Int = 50,
    val offset: Int = 0,
    val filters: LogsFilters = LogsFilters(),
    val selectedLogDetail: LogDetailItem? = null,
    val errorMessage: UiText? = null,
    val infoMessage: UiText? = null
) {
    val currentPage: Int
        get() = (offset / limit) + 1

    val totalPages: Int
        get() = if (total <= 0) 1 else ((total + limit - 1) / limit)

    val canLoadPrevious: Boolean
        get() = offset >= limit

    val canLoadNext: Boolean
        get() = offset + logs.size < total
}

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

    private val logsService = AppServices.logsService

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

    init {
        loadLogs()
    }

    fun onBackendChanged(value: String) = updateFilters { it.copy(backend = value) }
    fun onLogTypeChanged(value: String) = updateFilters { it.copy(logType = value) }
    fun onMethodChanged(value: String) = updateFilters { it.copy(method = value) }
    fun onStatusCodeChanged(value: String) = updateFilters { it.copy(statusCode = value) }
    fun onPathChanged(value: String) = updateFilters { it.copy(path = value) }
    fun onStartDateChanged(value: String) = updateFilters { it.copy(startDate = value) }
    fun onEndDateChanged(value: String) = updateFilters { it.copy(endDate = value) }

    fun applyFilters() {
        _state.update { it.copy(offset = 0) }
        loadLogs()
    }

    fun clearFilters() {
        _state.update {
            it.copy(
                filters = LogsFilters(),
                offset = 0
            )
        }
        loadLogs()
    }

    fun previousPage() {
        val current = _state.value
        if (!current.canLoadPrevious) return
        _state.update { it.copy(offset = (it.offset - it.limit).coerceAtLeast(0)) }
        loadLogs()
    }

    fun nextPage() {
        val current = _state.value
        if (!current.canLoadNext) return
        _state.update { it.copy(offset = it.offset + it.limit) }
        loadLogs()
    }

    fun retry() = loadLogs()

    fun loadLogDetail(id: String) {
        viewModelScope.launch {
            _state.update { it.copy(loadingDetail = true, errorMessage = null) }
            when (val result = logsService.loadLogDetail(id)) {
                is LogDetailResult.Success -> {
                    _state.update {
                        it.copy(
                            loadingDetail = false,
                            selectedLogDetail = result.item
                        )
                    }
                }

                is LogDetailResult.Error -> {
                    _state.update {
                        it.copy(
                            loadingDetail = false,
                            errorMessage = ViewModelStateUtils.dynamicOrFallback(
                                result.message,
                                UiText(R.string.logs_error_loading)
                            )
                        )
                    }
                }
            }
        }
    }

    fun dismissLogDetail() {
        _state.update { it.copy(selectedLogDetail = null) }
    }

    fun clearError() {
        _state.update { it.copy(errorMessage = null) }
    }

    fun clearInfo() {
        _state.update { it.copy(infoMessage = null) }
    }

    private fun loadLogs() {
        viewModelScope.launch {
            val current = _state.value
            _state.update { it.copy(loading = true, errorMessage = null) }
            when (
                val result = logsService.loadLogs(
                    limit = current.limit,
                    offset = current.offset,
                    backend = current.filters.backend,
                    logType = current.filters.logType,
                    method = current.filters.method,
                    statusCode = current.filters.statusCode,
                    path = current.filters.path,
                    startDate = current.filters.startDate,
                    endDate = current.filters.endDate
                )
            ) {
                is LogsResult.Success -> {
                    _state.update {
                        it.copy(
                            loading = false,
                            logs = result.data.logs,
                            total = result.data.total
                        )
                    }
                }

                is LogsResult.Error -> {
                    _state.update {
                        it.copy(
                            loading = false,
                            errorMessage = ViewModelStateUtils.dynamicOrFallback(
                                result.message,
                                UiText(R.string.logs_error_loading)
                            )
                        )
                    }
                }
            }
        }
    }

    private fun updateFilters(transform: (LogsFilters) -> LogsFilters) {
        _state.update { it.copy(filters = transform(it.filters)) }
    }
}
