package com.ponzischeme89.memby.ui

import androidx.compose.foundation.background
import androidx.compose.foundation.layout.Arrangement
import androidx.compose.foundation.layout.Box
import androidx.compose.foundation.layout.Column
import androidx.compose.foundation.layout.fillMaxSize
import androidx.compose.foundation.layout.padding
import androidx.compose.foundation.layout.width
import androidx.compose.runtime.Composable
import androidx.compose.ui.Modifier
import androidx.compose.ui.test.junit4.createComposeRule
import androidx.compose.ui.test.onRoot
import androidx.compose.ui.unit.dp
import com.github.takahirom.roborazzi.captureRoboImage
import com.ponzischeme89.memby.data.model.MediaRating
import com.ponzischeme89.memby.ui.theme.MembySurface
import org.junit.Rule
import org.junit.Test
import org.junit.runner.RunWith
import org.robolectric.RobolectricTestRunner
import org.robolectric.annotation.Config
import org.robolectric.annotation.GraphicsMode

/**
 * Renders the ratings strip to PNGs under `build/screenshots/ratings-strip/`.
 *
 * ```powershell
 * .\gradlew.bat :app:testDebugUnitTest --tests "*RatingsStripScreenshotTest"
 * ```
 *
 * The marks are the reason this exists: three of them are supplied artwork and one is
 * drawn, they have different aspect ratios, and whether they sit level with the score at
 * both sizes is a thing to look at rather than assert.
 */
@RunWith(RobolectricTestRunner::class)
@GraphicsMode(GraphicsMode.Mode.NATIVE)
@Config(sdk = [34], qualifiers = "w960dp-h540dp-television-xhdpi")
class RatingsStripScreenshotTest {

    @get:Rule
    val compose = createComposeRule()

    /** The detail page's case: every provider MDBList returns, at full size. */
    @Test
    fun `detail page strip`() {
        capture("ratings-strip-detail", ALL, width = 640)
    }

    /** The home hero and card case, where the strip is compact. */
    @Test
    fun `compact strip`() {
        capture("ratings-strip-compact", ALL, width = 480, compact = true)
    }

    /** A poster card: the width limit cuts it to the first three. */
    @Test
    fun `narrow card strip`() {
        capture("ratings-strip-narrow", ALL, width = 220, compact = true)
    }

    /** The mark for a provider no build has artwork for still has to read. */
    @Test
    fun `wordmark fallback`() {
        capture(
            "ratings-strip-wordmarks",
            listOf(
                MediaRating(source = "trakt", name = "Trakt", score = "83"),
                MediaRating(source = "mal", name = "MyAnimeList", score = "8.1"),
                MediaRating(source = "audience", name = "RT Audience", score = "91"),
            ),
            width = 640,
        )
    }

    /** One provider only, which is what an episode usually has. */
    @Test
    fun `single provider`() {
        capture(
            "ratings-strip-single",
            listOf(MediaRating(source = "imdb", name = "IMDb", score = "8.7")),
            width = 640,
        )
    }

    private fun capture(
        name: String,
        ratings: List<MediaRating>,
        width: Int,
        compact: Boolean = false,
    ) {
        compose.setContent { OnLauncherBackground(ratings, width, compact) }
        compose.onRoot().captureRoboImage("build/screenshots/ratings-strip/$name.png")
    }

    @Composable
    private fun OnLauncherBackground(
        ratings: List<MediaRating>,
        width: Int,
        compact: Boolean,
    ) {
        Box(Modifier.fillMaxSize().background(MembySurface)) {
            Column(
                modifier = Modifier.padding(40.dp).width(width.dp),
                verticalArrangement = Arrangement.spacedBy(16.dp),
            ) {
                RatingsStrip(ratings = ratings, visible = true, compact = compact)
            }
        }
    }

    private companion object {
        val ALL = listOf(
            MediaRating(source = "imdb", name = "IMDb", score = "8.2"),
            MediaRating(source = "tomatoes", name = "Rotten Tomatoes", score = "94"),
            MediaRating(source = "metacritic", name = "Metacritic", score = "81"),
            MediaRating(source = "letterboxd", name = "Letterboxd", score = "4.1"),
            MediaRating(source = "tmdb", name = "TMDb", score = "7.4"),
        )
    }
}
