package cy.hexor.furumi.domain.repository

import cy.hexor.furumi.domain.model.ArtistPage
import cy.hexor.furumi.domain.model.ArtistDetail
import cy.hexor.furumi.domain.model.ConnectedCommand
import cy.hexor.furumi.domain.model.ConnectedDevicesState
import cy.hexor.furumi.domain.model.ConnectedJamUser
import cy.hexor.furumi.domain.model.ConnectedPlaybackState
import cy.hexor.furumi.domain.model.ListeningHistoryPage
import cy.hexor.furumi.domain.model.OfflineState
import cy.hexor.furumi.domain.model.OfflineSyncSummary
import cy.hexor.furumi.domain.model.PlaylistCard
import cy.hexor.furumi.domain.model.PlaylistDetail
import cy.hexor.furumi.domain.model.ReleaseDetail
import cy.hexor.furumi.domain.model.SearchResults
import cy.hexor.furumi.domain.model.TrackCard
import kotlinx.coroutines.flow.StateFlow

interface PlayerRepository {
    val offlineState: StateFlow<OfflineState>

    suspend fun getArtists(
        page: Int = 1,
        limit: Int = 60,
        mine: Boolean = false
    ): Result<ArtistPage>

    suspend fun getArtistDetail(artistId: Long): Result<ArtistDetail>

    suspend fun getReleaseDetail(releaseId: Long): Result<ReleaseDetail>

    suspend fun search(query: String, limit: Int = 20): Result<SearchResults>

    suspend fun getListeningHistory(page: Int = 1, limit: Int = 20): Result<ListeningHistoryPage>

    suspend fun toggleLike(trackId: Long): Result<Boolean>

    suspend fun getLikedTrackIds(): Result<Set<Long>>

    suspend fun recordListeningHistory(
        trackId: Long,
        startedAt: Long,
        durationListened: Int,
        completed: Boolean
    ): Result<Unit>

    suspend fun getPlaylists(): Result<List<PlaylistCard>>

    suspend fun getPlaylistDetail(playlistId: Long): Result<PlaylistDetail>

    suspend fun createPlaylist(title: String): Result<PlaylistCard>

    suspend fun deletePlaylist(playlistId: Long): Result<Unit>

    suspend fun addTracksToPlaylist(playlistId: Long, trackIds: List<Long>): Result<Unit>

    suspend fun shareTrack(trackId: Long, title: String): Result<String>

    suspend fun pollConnectedDevice(
        playbackState: ConnectedPlaybackState?,
        currentJamId: String? = null
    ): Result<Pair<ConnectedDevicesState, List<ConnectedCommand>>>

    suspend fun setActiveDevice(deviceId: String): Result<ConnectedDevicesState>

    suspend fun sendConnectedDeviceCommand(
        targetDeviceId: String?,
        jamId: String?,
        command: String,
        payload: ConnectedPlaybackState? = null,
        tracks: List<TrackCard> = emptyList(),
        index: Int? = null,
        time: Double? = null,
        volume: Double? = null,
        shuffle: Boolean? = null,
        repeatMode: String? = null,
        fromIndex: Int? = null,
        toIndex: Int? = null
    ): Result<Unit>

    suspend fun createJam(): Result<ConnectedDevicesState>

    suspend fun joinJam(jamId: String): Result<ConnectedDevicesState>

    suspend fun leaveJam(jamId: String): Result<ConnectedDevicesState>

    suspend fun searchJamUsers(query: String, limit: Int = 10): Result<List<ConnectedJamUser>>

    suspend fun inviteToJam(jamId: String, inviteeUserIds: List<Long>): Result<ConnectedDevicesState>

    fun setOfflineModeEnabled(enabled: Boolean)

    fun setSaveListenedTracksEnabled(enabled: Boolean)

    fun setOfflineStorageLimit(limitBytes: Long)

    suspend fun syncOfflineLibrary(): Result<OfflineSyncSummary>

    suspend fun clearOfflineCache(): Result<Unit>
}
