package dev.adriankuta.flights.model.repository.usecases

import dev.adriankuta.flights.core.util.DefaultDispatcher
import dev.adriankuta.flights.domain.stations.ObserveAirportsGroupedByCountry
import dev.adriankuta.flights.domain.types.AirportInfo
import dev.adriankuta.flights.domain.types.Country
import dev.adriankuta.flights.model.datasource.airports.AirportsDatasource
import dev.adriankuta.flights.model.datasource.airports.entities.AirportInfoModel
import dev.adriankuta.flights.model.repository.mappers.toDomain
import dev.adriankuta.flights.model.repository.utilities.loadData
import dev.adriankuta.model.data.api.AirportService
import kotlinx.coroutines.CoroutineDispatcher
import kotlinx.coroutines.flow.Flow
import kotlinx.coroutines.withContext
import javax.inject.Inject

internal class ObserveAirportsGroupedByCountryImpl @Inject constructor(
    private val airportService: AirportService,
    private val airportsDatasource: AirportsDatasource,
    @DefaultDispatcher private val dispatcher: CoroutineDispatcher,
) : ObserveAirportsGroupedByCountry {
    override fun invoke(): Flow<Map<Country, List<AirportInfo>>?> = loadData(
        onCacheInvalidated = { cacheKey ->
            val response = airportService.getAirports("pl")
            airportsDatasource.setAirportsInfo(response, cacheKey)
        },
        observeCache = {
            airportsDatasource.airports
        },
        mapToDomain = { model ->
            withContext(dispatcher) {
                model.orEmpty().map(AirportInfoModel::toDomain).groupBy { airportInfo ->
                    airportInfo.country
                }.toSortedMap(compareBy { it.name })
            }
        },
    )
}
