package com.ponzischeme89.memby.ui.player

import androidx.media3.common.PlaybackException
import org.junit.Assert.assertEquals
import org.junit.Assert.assertFalse
import org.junit.Assert.assertNull
import org.junit.Assert.assertTrue
import org.junit.Test

class PlaybackRecoveryTest {

    @Test
    fun networkFailuresAreSafeToRetry() {
        val failure = describePlaybackFailure(
            PlaybackException.ERROR_CODE_IO_NETWORK_CONNECTION_FAILED,
        )

        assertEquals("Connection interrupted", failure.title)
        assertTrue(failure.canAutoRetry)
    }

    @Test
    fun decoderFailuresAutomaticallyRequestCompatibleStream() {
        val failure = describePlaybackFailure(
            PlaybackException.ERROR_CODE_DECODING_FORMAT_UNSUPPORTED,
        )

        assertEquals("Video format not supported", failure.title)
        assertTrue(failure.canAutoRetry)
        assertTrue(failure.requiresTranscode)
    }

    @Test
    fun staleOrRejectedStartupStreamsAutomaticallyResolveAFreshUrl() {
        val failure = describePlaybackFailure(
            PlaybackException.ERROR_CODE_IO_BAD_HTTP_STATUS,
        )

        assertTrue(failure.canAutoRetry)
        assertTrue(failure.requiresFreshStream)
        assertFalse(failure.requiresTranscode)
    }

    @Test
    fun genericPlayerTimeoutsAreSafeToRetry() {
        val failure = describePlaybackFailure(PlaybackException.ERROR_CODE_TIMEOUT)

        assertTrue(failure.canAutoRetry)
    }

    @Test
    fun malformedContainersDoNotLoopThroughTranscodingRetries() {
        val failure = describePlaybackFailure(
            PlaybackException.ERROR_CODE_PARSING_CONTAINER_MALFORMED,
        )

        assertFalse(failure.canAutoRetry)
        assertFalse(failure.requiresTranscode)
    }

    @Test
    fun automaticRetriesAreBoundedAndBackOff() {
        assertEquals(1_000L, automaticRetryDelayMs(1))
        assertEquals(3_000L, automaticRetryDelayMs(2))
        assertNull(automaticRetryDelayMs(3))
    }

    @Test
    fun prolongedMidProgrammeRebufferGetsOneCompatibilityFallback() {
        assertTrue(shouldRecoverProlongedRebuffer(true, false, false, false))
        assertFalse(shouldRecoverProlongedRebuffer(false, false, false, false))
        assertFalse(shouldRecoverProlongedRebuffer(true, true, false, false))
        assertFalse(shouldRecoverProlongedRebuffer(true, false, true, false))
        assertFalse(shouldRecoverProlongedRebuffer(true, false, false, true))
    }

    @Test
    fun replacementSessionDetectionKeepsSameSessionStreamSwapsTogether() {
        assertFalse(
            playbackSessionChanged("episode", "source-a", "session", "episode", "source-b", "session"),
        )
        assertTrue(
            playbackSessionChanged("episode", "source-a", "old", "episode", "source-b", "new"),
        )
        assertTrue(
            playbackSessionChanged("episode", "source-a", "", "episode", "source-b", ""),
        )
    }
}
