/*
 * SPDX-License-Identifier: GPL-3.0-or-later
 */
package com.runicgateway.app.ui.admin

import androidx.annotation.StringRes
import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.runicgateway.app.R
import com.runicgateway.app.core.result.ApiResult
import com.runicgateway.app.data.api.dto.SupportPageDto
import com.runicgateway.app.data.repository.AdminRepository
import com.runicgateway.app.ui.UiState
import com.runicgateway.app.ui.toUiState
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.flow.update
import kotlinx.coroutines.launch
import javax.inject.Inject

/**
 * Drives the support (help-page) queue (PLAN.md §1, M10): list open pages, reply
 * (optionally closing), and close, over `/admin/shard/pages…` (admin/moderator).
 * The list is served from shard state — empty when no tickets (or the shard is
 * offline); writes need a live sidecar and fail cleanly otherwise (§7).
 */
@HiltViewModel
class AdminSupportViewModel @Inject constructor(
    private val admin: AdminRepository,
) : ViewModel() {

    data class Feedback(val ok: Boolean, @param:StringRes val messageRes: Int)

    data class State(
        val pages: UiState<List<SupportPageDto>> = UiState.Loading,
        val busy: Boolean = false,
        val feedback: Feedback? = null,
    )

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

    init {
        load()
    }

    fun clearFeedback() = _state.update { it.copy(feedback = null) }

    fun load() {
        _state.update { it.copy(pages = UiState.Loading) }
        viewModelScope.launch { _state.update { it.copy(pages = admin.supportPages().toUiState()) } }
    }

    fun respond(id: String, message: String, close: Boolean) {
        if (message.isBlank()) {
            _state.update { it.copy(feedback = Feedback(false, R.string.admin_support_message_required)) }
            return
        }
        mutate(R.string.admin_support_responded) { admin.respondPage(id, message.trim(), close) }
    }

    fun close(id: String) = mutate(R.string.admin_support_closed) { admin.closePage(id) }

    private fun mutate(@StringRes okRes: Int, block: suspend () -> ApiResult<Unit>) {
        if (_state.value.busy) return
        _state.update { it.copy(busy = true, feedback = null) }
        viewModelScope.launch {
            val feedback = when (val r = block()) {
                is ApiResult.Ok -> Feedback(true, okRes)
                is ApiResult.HttpError -> Feedback(
                    false,
                    when (r.status) {
                        403 -> R.string.admin_forbidden
                        404 -> R.string.admin_support_unknown_page
                        503 -> R.string.admin_mod_shard_offline
                        else -> R.string.admin_action_failed
                    },
                )
                is ApiResult.NetworkError -> Feedback(false, R.string.error_network)
            }
            if (feedback.ok) load()
            _state.update { it.copy(busy = false, feedback = feedback) }
        }
    }
}
