package com.fabledsword.minstrel.cache.db.dao

import androidx.room.Dao
import androidx.room.Insert
import androidx.room.OnConflictStrategy
import androidx.room.Query
import androidx.room.Transaction
import com.fabledsword.minstrel.cache.db.entities.CachedLikeEntity
import kotlinx.coroutines.flow.Flow

@Dao
interface CachedLikeDao {
    /** All track IDs the user has liked. Audio-cache eviction uses this set. */
    @Query(
        "SELECT entityId FROM cached_likes " +
            "WHERE userId = :userId AND entityType = 'track'",
    )
    fun observeLikedTrackIds(userId: String): Flow<List<String>>

    @Query(
        "SELECT entityId FROM cached_likes " +
            "WHERE userId = :userId AND entityType = :entityType",
    )
    fun observeLikedIdsOfType(userId: String, entityType: String): Flow<List<String>>

    @Query(
        "SELECT EXISTS(SELECT 1 FROM cached_likes " +
            "WHERE userId = :userId AND entityType = :entityType AND entityId = :entityId)",
    )
    fun observeIsLiked(userId: String, entityType: String, entityId: String): Flow<Boolean>

    @Insert(onConflict = OnConflictStrategy.REPLACE)
    suspend fun upsertAll(rows: List<CachedLikeEntity>)

    @Query(
        "DELETE FROM cached_likes " +
            "WHERE userId = :userId AND entityType = :entityType AND entityId = :entityId",
    )
    suspend fun delete(userId: String, entityType: String, entityId: String)

    @Query("DELETE FROM cached_likes WHERE userId = :userId")
    suspend fun clearForUser(userId: String)

    /**
     * Atomically replaces the user's entire cached_likes set with
     * [rows]. Used by [com.fabledsword.minstrel.likes.data.LikesRepository.refreshIds]
     * so cross-device unlikes (a row that the server no longer
     * surfaces) get removed from the local cache — drift #570
     * caught the missing delete pass that left stale Liked tab
     * entries pointing at tracks the user had unliked elsewhere.
     */
    @Transaction
    suspend fun replaceAllForUser(userId: String, rows: List<CachedLikeEntity>) {
        clearForUser(userId)
        upsertAll(rows)
    }
}
