package ru.fincode.tsudesk.feature.schedule.data.local

import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.flow.combine
import kotlinx.coroutines.flow.distinctUntilChanged
import kotlinx.coroutines.flow.emitAll
import kotlinx.coroutines.flow.first
import kotlinx.coroutines.flow.flatMapLatest
import kotlinx.coroutines.flow.flow
import kotlinx.coroutines.flow.flowOf
import kotlinx.coroutines.flow.map
import kotlinx.coroutines.flow.onStart
import ru.fincode.tsudesk.core.database.api.schedule.ScheduleDao
import ru.fincode.tsudesk.feature.schedule.data.datasource.ScheduleLocalDataSource
import ru.fincode.tsudesk.feature.schedule.domain.model.ScheduleEntity
import javax.inject.Inject

class ScheduleLocalDataSourceImpl @Inject constructor(
    private val dao: ScheduleDao
) : ScheduleLocalDataSource {

    override suspend fun saveSchedule(key: String, schedule: ScheduleEntity) {
        val (scheduleCache, lessonsCache) = schedule.toCache(key)
        dao.replaceSchedule(key, scheduleCache, lessonsCache)
    }

    override suspend fun loadSchedule(key: String): ScheduleEntity? {
        val schedule = dao.getSchedule(key) ?: return null
        val lessons = dao.getLessons(key)
        return schedule.toDomain(lessons)
    }

    override fun observeSchedule(key: String): Flow<ScheduleEntity?> = flow {
        emitAll(
            dao.observeSchedule(key).map { schedule ->
                if (schedule == null) {
                    null
                } else {
                    val lessons = dao.observeLessons(key)
                        .first()
                    schedule.toDomain(lessons)
                }
            }
        )
    }.distinctUntilChanged()

    override suspend fun removeSchedule(key: String) {
        dao.deleteLessonsByKey(key)
    }
}
