package com.tt.honeyDue.viewmodel

import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.tt.honeyDue.data.DataManager
import com.tt.honeyDue.data.IDataManager
import com.tt.honeyDue.models.*
import com.tt.honeyDue.network.APILayer
import com.tt.honeyDue.network.ApiResult
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.stateIn
import kotlinx.coroutines.launch

/**
 * ContractorViewModel — read-state derived from [IDataManager].
 *
 * Reads ([contractorsState], [contractorDetailState]) reactively mirror
 * [IDataManager.contractors] / [IDataManager.contractorDetail] so the
 * VM reflects any DataManager update instantly (API success write,
 * fixture seed, etc.). Mutations (create/update/delete/toggleFavorite)
 * remain owned by the VM as one-shot [ApiResult] fields.
 */
class ContractorViewModel(
    private val dataManager: IDataManager = DataManager,
    initialSelectedContractorId: Int? = null,
) : ViewModel() {

    // ---------- Read state ----------

    val contractorsState: StateFlow<ApiResult<List<ContractorSummary>>> =
        dataManager.contractors
            .map { list -> if (list.isNotEmpty()) ApiResult.Success(list) else ApiResult.Idle }
            .stateIn(
                viewModelScope,
                SharingStarted.Eagerly,
                dataManager.contractors.value
                    .takeIf { it.isNotEmpty() }
                    ?.let { ApiResult.Success(it) } ?: ApiResult.Idle,
            )

    // `initialSelectedContractorId` seeds this in construction order so the
    // `stateIn` initial-value closure below observes the selected id *and*
    // the seeded `dataManager.contractorDetail[id]` on first subscription —
    // used by the parity-gallery snapshot harness to render populated
    // detail screens on the very first composition frame.
    private val _selectedContractorId = MutableStateFlow<Int?>(initialSelectedContractorId)

    val contractorDetailState: StateFlow<ApiResult<Contractor>> =
        combine(_selectedContractorId, dataManager.contractorDetail) { id, map ->
            if (id == null) ApiResult.Idle
            else map[id]?.let { ApiResult.Success(it) } ?: ApiResult.Idle
        }.stateIn(
            viewModelScope,
            SharingStarted.Eagerly,
            _selectedContractorId.value?.let { id ->
                dataManager.contractorDetail.value[id]?.let { ApiResult.Success(it) }
            } ?: ApiResult.Idle,
        )

    // ---------- Loading / error ----------

    private val _isLoading = MutableStateFlow(false)
    val isLoading: StateFlow<Boolean> = _isLoading
    private val _loadError = MutableStateFlow<String?>(null)
    val loadError: StateFlow<String?> = _loadError

    // ---------- Mutation-feedback ----------

    private val _createState = MutableStateFlow<ApiResult<Contractor>>(ApiResult.Idle)
    val createState: StateFlow<ApiResult<Contractor>> = _createState

    private val _updateState = MutableStateFlow<ApiResult<Contractor>>(ApiResult.Idle)
    val updateState: StateFlow<ApiResult<Contractor>> = _updateState

    private val _deleteState = MutableStateFlow<ApiResult<Unit>>(ApiResult.Idle)
    val deleteState: StateFlow<ApiResult<Unit>> = _deleteState

    private val _toggleFavoriteState = MutableStateFlow<ApiResult<Contractor>>(ApiResult.Idle)
    val toggleFavoriteState: StateFlow<ApiResult<Contractor>> = _toggleFavoriteState

    // ---------- Loaders (write-through to DataManager) ----------

    fun loadContractors(
        specialty: String? = null,
        isFavorite: Boolean? = null,
        isActive: Boolean? = null,
        search: String? = null,
        forceRefresh: Boolean = false,
    ) {
        viewModelScope.launch {
            _isLoading.value = true
            _loadError.value = null
            _loadError.value = (APILayer.getContractors(
                specialty = specialty,
                isFavorite = isFavorite,
                isActive = isActive,
                search = search,
                forceRefresh = forceRefresh,
            ) as? ApiResult.Error)?.message
            _isLoading.value = false
        }
    }

    fun loadContractorDetail(id: Int) {
        viewModelScope.launch {
            _selectedContractorId.value = id
            _isLoading.value = true
            _loadError.value = null
            _loadError.value = (APILayer.getContractor(id) as? ApiResult.Error)?.message
            _isLoading.value = false
        }
    }

    fun selectContractor(id: Int?) {
        _selectedContractorId.value = id
    }

    // ---------- Mutations ----------

    fun createContractor(request: ContractorCreateRequest) {
        viewModelScope.launch {
            _createState.value = ApiResult.Loading
            _createState.value = APILayer.createContractor(request)
        }
    }

    fun updateContractor(id: Int, request: ContractorUpdateRequest) {
        viewModelScope.launch {
            _updateState.value = ApiResult.Loading
            _updateState.value = APILayer.updateContractor(id, request)
        }
    }

    fun deleteContractor(id: Int) {
        viewModelScope.launch {
            _deleteState.value = ApiResult.Loading
            _deleteState.value = APILayer.deleteContractor(id)
        }
    }

    fun toggleFavorite(id: Int) {
        viewModelScope.launch {
            _toggleFavoriteState.value = ApiResult.Loading
            _toggleFavoriteState.value = APILayer.toggleFavorite(id)
        }
    }

    fun resetCreateState() { _createState.value = ApiResult.Idle }
    fun resetUpdateState() { _updateState.value = ApiResult.Idle }
    fun resetDeleteState() { _deleteState.value = ApiResult.Idle }
    fun resetToggleFavoriteState() { _toggleFavoriteState.value = ApiResult.Idle }
}
