package pl.firmatpp.kierowca.ui

import pl.firmatpp.kierowca.data.model.DriverRouteDto
import pl.firmatpp.kierowca.data.model.RoutePhotoDto
import pl.firmatpp.kierowca.data.upload.RouteActionEntity
import pl.firmatpp.kierowca.data.upload.RouteActionStatus
import pl.firmatpp.kierowca.data.upload.RouteActionType

data class ProjectedDriverRoute(
    val route: DriverRouteDto,
    val visibleActions: List<RouteActionEntity>,
    val loadingWeightPending: Boolean,
    val unloadingWeightPending: Boolean,
)

internal val routeActionVisibleStatuses = setOf(
    RouteActionStatus.Pending,
    RouteActionStatus.WaitingForPhotos,
    RouteActionStatus.Syncing,
    RouteActionStatus.FailedRetryable,
    RouteActionStatus.FailedConflict,
    RouteActionStatus.FailedPermanent,
)

private val routeActionProjectionStatuses = routeActionVisibleStatuses + RouteActionStatus.Confirmed

fun projectDriverRoute(route: DriverRouteDto, actions: List<RouteActionEntity>): ProjectedDriverRoute {
    val visible = actions
        .filter { it.routeId == route.id && it.status in routeActionVisibleStatuses }
    val projectable = actions
        .filter { it.routeId == route.id && it.status in routeActionProjectionStatuses }
    var projectedRoute = route
    var loadingWeightPending = false
    var unloadingWeightPending = false

    projectable
        .sortedWith(compareBy<RouteActionEntity> { it.createdAtEpochMillis }.thenBy { it.clientActionId })
        .forEach { action ->
            when (action.action) {
                RouteActionType.Start -> {
                    projectedRoute = projectedRoute.copy(
                        status = "W TRAKCIE",
                        driverStatus = "W TRAKCIE",
                        loadingWeight = action.weight,
                        trackingStatus = "active",
                        photos = projectedRoute.safePhotos(),
                    )
                    loadingWeightPending = action.status != RouteActionStatus.Confirmed
                }
                RouteActionType.Finish -> {
                    projectedRoute = projectedRoute.copy(
                        status = "ZAKOŃCZONA",
                        driverStatus = "ZAKOŃCZONA",
                        unloadingWeight = action.weight,
                        trackingStatus = "finished",
                        completedAt = action.occurredAt,
                        photos = projectedRoute.safePhotos(),
                    )
                    unloadingWeightPending = action.status != RouteActionStatus.Confirmed
                }
            }
        }

    return ProjectedDriverRoute(
        route = projectedRoute,
        visibleActions = visible.sortedWith(
            compareByDescending<RouteActionEntity> { it.createdAtEpochMillis }.thenBy { it.clientActionId },
        ),
        loadingWeightPending = loadingWeightPending,
        unloadingWeightPending = unloadingWeightPending,
    )
}

fun projectDriverRoutes(routes: List<DriverRouteDto>, actions: List<RouteActionEntity>): List<DriverRouteDto> =
    routes.map { route -> projectDriverRoute(route, actions).route }

fun routeActionNeedsAttention(status: String): Boolean =
    status == RouteActionStatus.FailedConflict || status == RouteActionStatus.FailedPermanent

internal fun DriverRouteDto.safePhotos(): List<RoutePhotoDto> = photos.orEmpty()
