package pl.firmatpp.kierowca.data.upload

import androidx.room.Dao
import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query
import kotlinx.coroutines.flow.Flow

@Dao
interface RouteActionDao {
    @Insert(onConflict = OnConflictStrategy.REPLACE)
    suspend fun upsert(action: RouteActionEntity)

    @Query("SELECT * FROM route_actions WHERE clientActionId = :clientActionId LIMIT 1")
    suspend fun find(clientActionId: String): RouteActionEntity?

    @Query("SELECT * FROM route_actions WHERE status != 'CONFIRMED'")
    suspend fun allUnsent(): List<RouteActionEntity>

    @Query("DELETE FROM route_actions WHERE clientActionId = :clientActionId")
    suspend fun delete(clientActionId: String)

    @Query("DELETE FROM route_actions")
    suspend fun deleteAll()

    @Query("DELETE FROM route_actions WHERE status = 'CONFIRMED' AND updatedAtEpochMillis < :beforeEpochMillis")
    suspend fun pruneConfirmed(beforeEpochMillis: Long)

    @Query("SELECT * FROM route_actions WHERE status = 'WAITING_FOR_PHOTOS'")
    suspend fun waitingForPhotosActions(): List<RouteActionEntity>

    @Query(
        """
        SELECT * FROM route_actions
        WHERE routeId = :routeId
        AND status IN ('PENDING', 'WAITING_FOR_PHOTOS', 'SYNCING', 'CONFIRMED', 'FAILED_RETRYABLE', 'FAILED_CONFLICT', 'FAILED_PERMANENT')
        ORDER BY createdAtEpochMillis DESC
        """,
    )
    fun observeUnresolvedForRoute(routeId: String): Flow<List<RouteActionEntity>>

    @Query(
        """
        SELECT * FROM route_actions
        WHERE status IN ('PENDING', 'WAITING_FOR_PHOTOS', 'SYNCING', 'FAILED_RETRYABLE', 'FAILED_CONFLICT', 'FAILED_PERMANENT')
        OR clientActionId IN (
            SELECT confirmed.clientActionId
            FROM route_actions AS confirmed
            WHERE confirmed.status = 'CONFIRMED'
            AND confirmed.routeId = route_actions.routeId
            ORDER BY confirmed.createdAtEpochMillis DESC
            LIMIT 2
        )
        ORDER BY createdAtEpochMillis DESC
        """,
    )
    fun observeVisibleActions(): Flow<List<RouteActionEntity>>

    @Query(
        """
        UPDATE route_actions
        SET status = :status,
            lastError = :lastError,
            attemptCount = attemptCount + :attemptIncrement,
            updatedAtEpochMillis = :updatedAt
        WHERE clientActionId = :clientActionId
        """,
    )
    suspend fun updateStatus(
        clientActionId: String,
        status: String,
        lastError: String?,
        attemptIncrement: Int,
        updatedAt: Long = System.currentTimeMillis(),
    )
}
