package com.pixelized.headache.ui.page.event.list

import androidx.lifecycle.ViewModel
import androidx.lifecycle.viewModelScope
import com.pixelized.headache.repository.event.Event
import com.pixelized.headache.repository.event.EventRepository
import com.pixelized.headache.ui.navigation.destination.EventDestination
import com.pixelized.headache.utils.extention.isSameMonth
import dagger.assisted.Assisted
import dagger.assisted.AssistedFactory
import dagger.assisted.AssistedInject
import dagger.hilt.android.lifecycle.HiltViewModel
import kotlinx.coroutines.ExperimentalCoroutinesApi
import kotlinx.coroutines.flow.MutableStateFlow
import kotlinx.coroutines.flow.SharingStarted
import kotlinx.coroutines.flow.StateFlow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.mapLatest
import kotlinx.coroutines.flow.stateIn

@HiltViewModel(assistedFactory = EventViewModel.Factory::class)
class EventViewModel @AssistedInject constructor(
    eventRepository: EventRepository,
    eventItemFactory: EventItemFactory,
    @Assisted val argument: EventDestination,
) : ViewModel() {

    private val misspelledFilterFlow = MutableStateFlow(argument.misspelledFilter)
    val misspelledFilter: StateFlow<Boolean> = misspelledFilterFlow

    private val invalidFilterFlow = MutableStateFlow(argument.invalidFilter)
    val invalidFilter: StateFlow<Boolean> = invalidFilterFlow

    @OptIn(ExperimentalCoroutinesApi::class)
    val events: StateFlow<List<EventItemUio>> = combine(
        when (argument.date) {
            null -> eventRepository.eventsListFlow()
            else -> eventRepository.eventsListFlow()
                .mapLatest { events ->
                    events.filter { event ->
                        event.date isSameMonth argument.date
                    }
                }
        },
        misspelledFilterFlow,
        invalidFilterFlow,
        transform = { events, misspelled, invalid ->
            if (!misspelled && !invalid) {
                events
            } else {
                events.filter {
                    misspelled && it.isMisspelled || invalid && it.isValid.not()
                }
            }
        }
    ).mapLatest { events: Collection<Event> ->
        eventItemFactory.convertToUio(
            events = events,
        )
    }.stateIn(
        scope = viewModelScope,
        started = SharingStarted.Lazily,
        initialValue = emptyList(),
    )

    fun toggleMisspelledFilter() {
        misspelledFilterFlow.value = !misspelledFilterFlow.value
    }

    fun toggleErrorFilter() {
        invalidFilterFlow.value = !invalidFilterFlow.value
    }

    @AssistedFactory
    interface Factory {
        fun create(navKey: EventDestination): EventViewModel
    }
}