package com.tt.honeyDue.viewmodel

import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.tt.honeyDue.models.Residence
import com.tt.honeyDue.models.ResidenceCreateRequest
import com.tt.honeyDue.models.TotalSummary
import com.tt.honeyDue.models.MyResidencesResponse
import com.tt.honeyDue.models.TaskColumnsResponse
import com.tt.honeyDue.models.ContractorSummary
import com.tt.honeyDue.network.ApiResult
import com.tt.honeyDue.network.APILayer
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.launch

class ResidenceViewModel : ViewModel() {

    private val _residencesState = MutableStateFlow<ApiResult<List<Residence>>>(ApiResult.Idle)
    val residencesState: StateFlow<ApiResult<List<Residence>>> = _residencesState

    private val _summaryState = MutableStateFlow<ApiResult<TotalSummary>>(ApiResult.Idle)
    val summaryState: StateFlow<ApiResult<TotalSummary>> = _summaryState

    private val _createResidenceState = MutableStateFlow<ApiResult<Residence>>(ApiResult.Idle)
    val createResidenceState: StateFlow<ApiResult<Residence>> = _createResidenceState

    private val _updateResidenceState = MutableStateFlow<ApiResult<Residence>>(ApiResult.Idle)
    val updateResidenceState: StateFlow<ApiResult<Residence>> = _updateResidenceState

    private val _residenceTasksState = MutableStateFlow<ApiResult<TaskColumnsResponse>>(ApiResult.Idle)
    val residenceTasksState: StateFlow<ApiResult<TaskColumnsResponse>> = _residenceTasksState

    private val _myResidencesState = MutableStateFlow<ApiResult<MyResidencesResponse>>(ApiResult.Idle)
    val myResidencesState: StateFlow<ApiResult<MyResidencesResponse>> = _myResidencesState

    private val _cancelTaskState = MutableStateFlow<ApiResult<com.tt.honeyDue.models.CustomTask>>(ApiResult.Idle)
    val cancelTaskState: StateFlow<ApiResult<com.tt.honeyDue.models.CustomTask>> = _cancelTaskState

    private val _uncancelTaskState = MutableStateFlow<ApiResult<com.tt.honeyDue.models.CustomTask>>(ApiResult.Idle)
    val uncancelTaskState: StateFlow<ApiResult<com.tt.honeyDue.models.CustomTask>> = _uncancelTaskState

    private val _updateTaskState = MutableStateFlow<ApiResult<com.tt.honeyDue.models.CustomTask>>(ApiResult.Idle)
    val updateTaskState: StateFlow<ApiResult<com.tt.honeyDue.models.CustomTask>> = _updateTaskState

    private val _generateReportState = MutableStateFlow<ApiResult<com.tt.honeyDue.network.GenerateReportResponse>>(ApiResult.Idle)
    val generateReportState: StateFlow<ApiResult<com.tt.honeyDue.network.GenerateReportResponse>> = _generateReportState

    private val _deleteResidenceState = MutableStateFlow<ApiResult<Unit>>(ApiResult.Idle)
    val deleteResidenceState: StateFlow<ApiResult<Unit>> = _deleteResidenceState

    private val _residenceContractorsState = MutableStateFlow<ApiResult<List<ContractorSummary>>>(ApiResult.Idle)
    val residenceContractorsState: StateFlow<ApiResult<List<ContractorSummary>>> = _residenceContractorsState

    /**
     * Load residences from cache. If cache is empty or force refresh is requested,
     * fetch from API and update cache.
     */
    fun loadResidences(forceRefresh: Boolean = false) {
        viewModelScope.launch {
            _residencesState.value = ApiResult.Loading
            _residencesState.value = APILayer.getResidences(forceRefresh = forceRefresh)
        }
    }

    fun loadSummary(forceRefresh: Boolean = false) {
        viewModelScope.launch {
            _summaryState.value = ApiResult.Loading
            _summaryState.value = APILayer.getSummary(forceRefresh = forceRefresh)
        }
    }

    fun getResidence(id: Int, onResult: (ApiResult<Residence>) -> Unit) {
        viewModelScope.launch {
            val result = APILayer.getResidence(id)
            onResult(result)
        }
    }

    fun createResidence(request: ResidenceCreateRequest) {
        viewModelScope.launch {
            _createResidenceState.value = ApiResult.Loading
            _createResidenceState.value = APILayer.createResidence(request)
        }
    }

    fun resetResidenceTasksState() {
        _residenceTasksState.value = ApiResult.Idle
    }

    fun loadResidenceTasks(residenceId: Int) {
        viewModelScope.launch {
            _residenceTasksState.value = ApiResult.Loading
            _residenceTasksState.value = APILayer.getTasksByResidence(residenceId)
        }
    }

    fun updateResidence(residenceId: Int, request: ResidenceCreateRequest) {
        viewModelScope.launch {
            _updateResidenceState.value = ApiResult.Loading
            _updateResidenceState.value = APILayer.updateResidence(residenceId, request)
        }
    }

    fun resetCreateState() {
        _createResidenceState.value = ApiResult.Idle
    }

    fun resetUpdateState() {
        _updateResidenceState.value = ApiResult.Idle
    }

    fun loadMyResidences(forceRefresh: Boolean = false) {
        viewModelScope.launch {
            _myResidencesState.value = ApiResult.Loading
            _myResidencesState.value = APILayer.getMyResidences(forceRefresh = forceRefresh)
        }
    }

    fun cancelTask(taskId: Int) {
        viewModelScope.launch {
            _cancelTaskState.value = ApiResult.Loading
            _cancelTaskState.value = APILayer.cancelTask(taskId)
        }
    }

    fun uncancelTask(taskId: Int) {
        viewModelScope.launch {
            _uncancelTaskState.value = ApiResult.Loading
            _uncancelTaskState.value = APILayer.uncancelTask(taskId)
        }
    }

    fun updateTask(taskId: Int, request: com.tt.honeyDue.models.TaskCreateRequest) {
        viewModelScope.launch {
            _updateTaskState.value = ApiResult.Loading
            _updateTaskState.value = APILayer.updateTask(taskId, request)
        }
    }

    fun resetCancelTaskState() {
        _cancelTaskState.value = ApiResult.Idle
    }

    fun resetUncancelTaskState() {
        _uncancelTaskState.value = ApiResult.Idle
    }

    fun resetUpdateTaskState() {
        _updateTaskState.value = ApiResult.Idle
    }

    fun generateTasksReport(residenceId: Int, email: String? = null) {
        viewModelScope.launch {
            _generateReportState.value = ApiResult.Loading
            _generateReportState.value = APILayer.generateTasksReport(residenceId, email)
        }
    }

    fun resetGenerateReportState() {
        _generateReportState.value = ApiResult.Idle
    }

    fun deleteResidence(residenceId: Int) {
        viewModelScope.launch {
            _deleteResidenceState.value = ApiResult.Loading
            _deleteResidenceState.value = APILayer.deleteResidence(residenceId)
        }
    }

    fun resetDeleteResidenceState() {
        _deleteResidenceState.value = ApiResult.Idle
    }

    private val _joinResidenceState = MutableStateFlow<ApiResult<com.tt.honeyDue.models.JoinResidenceResponse>>(ApiResult.Idle)
    val joinResidenceState: StateFlow<ApiResult<com.tt.honeyDue.models.JoinResidenceResponse>> = _joinResidenceState

    fun joinWithCode(code: String) {
        viewModelScope.launch {
            _joinResidenceState.value = ApiResult.Loading
            _joinResidenceState.value = APILayer.joinWithCode(code)
        }
    }

    fun resetJoinResidenceState() {
        _joinResidenceState.value = ApiResult.Idle
    }

    fun loadResidenceContractors(residenceId: Int) {
        viewModelScope.launch {
            _residenceContractorsState.value = ApiResult.Loading
            _residenceContractorsState.value = APILayer.getContractorsByResidence(residenceId)
        }
    }

    fun resetResidenceContractorsState() {
        _residenceContractorsState.value = ApiResult.Idle
    }
}
