package melody.offline.music.util

import android.net.Uri
import android.os.Build
import android.text.format.DateUtils
import androidx.annotation.OptIn
import androidx.core.net.toUri
import androidx.core.os.bundleOf
import androidx.media3.common.MediaItem
import androidx.media3.common.MediaMetadata
import androidx.media3.common.util.UnstableApi
import melody.offline.music.bean.FavoriteBean
import melody.offline.music.bean.OfflineBean
import melody.offline.music.bean.PlaylistItem
import melody.offline.music.innertube.Innertube
import melody.offline.music.innertube.models.bodies.ContinuationBody
import melody.offline.music.innertube.requests.playlistPage
import melody.offline.music.innertube.utils.plus

val OfflineBean.asMediaItem: MediaItem
    @OptIn(UnstableApi::class) get() = MediaItem.Builder().setMediaId(videoId).setUri(videoId)
        .setCustomCacheKey(videoId).setMediaMetadata(
            MediaMetadata.Builder().setTitle(title).setArtist(name)
                .setArtworkUri(thumbnail?.toUri()).build()
        ).build()

val FavoriteBean.asMediaItem: MediaItem
    @OptIn(UnstableApi::class) get() = MediaItem.Builder().setMediaId(videoId).setUri(videoId)
        .setCustomCacheKey(videoId).setMediaMetadata(
            MediaMetadata.Builder().setTitle(title).setArtist(name)
                .setArtworkUri(thumbnail?.toUri()).build()
        ).build()

val PlaylistItem.asMediaItem: MediaItem
    @OptIn(UnstableApi::class) get() = MediaItem.Builder().setMediaId(videoId).setUri(videoId)
        .setCustomCacheKey(videoId).setMediaMetadata(
            MediaMetadata.Builder().setTitle(title).setArtist(name)
                .setArtworkUri(thumbnail?.toUri()).build()
        ).build()

val Innertube.SongItem.asMediaItem: MediaItem
    @OptIn(UnstableApi::class) get() = MediaItem.Builder().setMediaId(key).setUri(key)
        .setCustomCacheKey(key).setMediaMetadata(
            MediaMetadata.Builder().setTitle(info?.name)
                .setArtist(authors?.joinToString("") { it.name ?: "" }).setAlbumTitle(album?.name)
                .setArtworkUri(bigThumbnail?.url?.toUri()).setExtras(
                    bundleOf(
                        "albumId" to album?.endpoint?.browseId,
                        "durationText" to durationText,
                        "artistNames" to authors?.filter { it.endpoint != null }
                            ?.mapNotNull { it.name },
                        "artistIds" to authors?.mapNotNull { it.endpoint?.browseId },
                    )
                ).build()
        ).build()

val Innertube.MoPlaylistOrAlbumPage.MoPlaylistOrAlbumListBean.asPlaylistItem: PlaylistItem
    get() = PlaylistItem(
        videoId = videoId ?: "",
        title = title ?: "",
        name = name ?: "",
        thumbnail = thumbnailUrl ?: backupThumbnailUrl,
        bytesDownloaded = bytesDownloaded,
        size = size,
        isOffline = isOffline ?: false,
        isFavorite = isFavorite ?: false
    )

fun String?.thumbnail(size: Int): String? {
    return when {
        this?.startsWith("https://lh3.googleusercontent.com") == true -> "$this-w$size-h$size"
        this?.startsWith("https://yt3.ggpht.com") == true -> "$this-w$size-h$size-s$size"
        else -> this
    }
}

fun Uri?.thumbnail(size: Int): Uri? {
    return toString().thumbnail(size)?.toUri()
}

fun formatAsDuration(millis: Long) = DateUtils.formatElapsedTime(millis / 1000).removePrefix("0")

suspend fun Result<Innertube.PlaylistOrAlbumPage>.completed(): Result<Innertube.PlaylistOrAlbumPage>? {
    var playlistPage = getOrNull() ?: return null

    while (playlistPage.songsPage?.continuation != null) {
        val continuation = playlistPage.songsPage?.continuation!!
        val otherPlaylistPageResult =
            Innertube.playlistPage(ContinuationBody(continuation = continuation)) ?: break

        if (otherPlaylistPageResult.isFailure) break

        otherPlaylistPageResult.getOrNull()?.let { otherSongsPage ->
            playlistPage = playlistPage.copy(songsPage = playlistPage.songsPage + otherSongsPage)
        }
    }

    return Result.success(playlistPage)
}

inline val isAtLeastAndroid6
    get() = Build.VERSION.SDK_INT >= Build.VERSION_CODES.M

inline val isAtLeastAndroid8
    get() = Build.VERSION.SDK_INT >= Build.VERSION_CODES.O

inline val isAtLeastAndroid12
    get() = Build.VERSION.SDK_INT >= Build.VERSION_CODES.S

inline val isAtLeastAndroid13
    get() = Build.VERSION.SDK_INT >= Build.VERSION_CODES.TIRAMISU
