package com.tt.honeyDue.ui.screens.task

import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.tt.honeyDue.models.TaskCreateRequest
import com.tt.honeyDue.models.TaskResponse
import com.tt.honeyDue.network.APILayer
import com.tt.honeyDue.network.ApiResult
import kotlinx.coroutines.flow.FlowCollector
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.asStateFlow
import kotlinx.coroutines.launch

/**
 * State-logic layer for [AddTaskWithResidenceScreen] (P2 Stream I).
 *
 * The residence is pre-selected via [residenceId] (Android port of the iOS
 * AddTaskWithResidenceView / TaskFormView combo, where a non-null
 * residenceId skips the picker). On submit, builds a [TaskCreateRequest]
 * with residenceId attached and calls [APILayer.createTask]. On success,
 * the screen invokes onCreated so the caller can pop and refresh.
 *
 * [createTask] is injected for unit-testability.
 */
class AddTaskWithResidenceViewModel(
    private val residenceId: Int,
    private val createTask: suspend (TaskCreateRequest) -> ApiResult<TaskResponse> = { req ->
        APILayer.createTask(req)
    }
) : ViewModel() {

    // --- Form fields ---

    private val _title = MutableStateFlow("")
    val title: StateFlow<String> = _title.asStateFlow()

    private val _description = MutableStateFlow("")
    val description: StateFlow<String> = _description.asStateFlow()

    private val _priorityId = MutableStateFlow<Int?>(null)
    val priorityId: StateFlow<Int?> = _priorityId.asStateFlow()

    private val _categoryId = MutableStateFlow<Int?>(null)
    val categoryId: StateFlow<Int?> = _categoryId.asStateFlow()

    private val _frequencyId = MutableStateFlow<Int?>(null)
    val frequencyId: StateFlow<Int?> = _frequencyId.asStateFlow()

    /** Optional ISO date string yyyy-MM-dd or blank. */
    private val _dueDate = MutableStateFlow("")
    val dueDate: StateFlow<String> = _dueDate.asStateFlow()

    /** Optional decimal string ("" = no estimate). */
    private val _estimatedCost = MutableStateFlow("")
    val estimatedCost: StateFlow<String> = _estimatedCost.asStateFlow()

    // --- Validation + submit state ---

    private val _titleError = MutableStateFlow<String?>(null)
    val titleError: StateFlow<String?> = _titleError.asStateFlow()

    private val _submitState = MutableStateFlow<ApiResult<TaskResponse>>(ApiResult.Idle)
    val submitState: StateFlow<ApiResult<TaskResponse>> = _submitState.asStateFlow()

    /**
     * True once title is non-blank. The screen disables the submit button on
     * false. Implemented as a read-only view over [_title] so the derived
     * value is always fresh without relying on a collector coroutine — keeps
     * unit tests synchronous (assert on .value immediately after a setter).
     */
    @OptIn(kotlinx.coroutines.ExperimentalCoroutinesApi::class)
    val canSubmit: StateFlow<Boolean> = object : StateFlow<Boolean> {
        override val replayCache: List<Boolean>
            get() = listOf(value)
        override val value: Boolean
            get() = _title.value.isNotBlank()
        override suspend fun collect(collector: FlowCollector<Boolean>): Nothing {
            _title.collect { collector.emit(it.isNotBlank()) }
        }
    }

    // --- Setters ---

    fun onTitleChange(value: String) {
        _title.value = value
        if (value.isNotBlank()) _titleError.value = null
    }

    fun onDescriptionChange(value: String) { _description.value = value }
    fun onPriorityIdChange(value: Int?) { _priorityId.value = value }
    fun onCategoryIdChange(value: Int?) { _categoryId.value = value }
    fun onFrequencyIdChange(value: Int?) { _frequencyId.value = value }
    fun onDueDateChange(value: String) { _dueDate.value = value }
    fun onEstimatedCostChange(value: String) { _estimatedCost.value = value }

    // --- Submit ---

    /**
     * Validates the form and submits via [createTask]. On success, fires
     * [onSuccess] — the screen uses that to pop and refresh the caller.
     * On error, [submitState] is set to [ApiResult.Error] so the screen
     * can surface an inline error without popping.
     */
    fun submit(onSuccess: () -> Unit) {
        val currentTitle = _title.value.trim()
        if (currentTitle.isEmpty()) {
            _titleError.value = "Title is required"
            return
        }

        val request = TaskCreateRequest(
            residenceId = residenceId,
            title = currentTitle,
            description = _description.value.ifBlank { null },
            categoryId = _categoryId.value,
            priorityId = _priorityId.value,
            frequencyId = _frequencyId.value,
            dueDate = _dueDate.value.ifBlank { null },
            estimatedCost = _estimatedCost.value.ifBlank { null }?.toDoubleOrNull()
        )

        viewModelScope.launch {
            _submitState.value = ApiResult.Loading
            when (val result = createTask(request)) {
                is ApiResult.Success -> {
                    _submitState.value = result
                    onSuccess()
                }
                is ApiResult.Error -> _submitState.value = result
                ApiResult.Loading -> _submitState.value = ApiResult.Loading
                ApiResult.Idle -> _submitState.value = ApiResult.Idle
            }
        }
    }

    fun resetSubmitState() {
        _submitState.value = ApiResult.Idle
    }
}
