package com.yorvana.screenshots

import android.util.Log
import androidx.compose.ui.test.junit4.createAndroidComposeRule
import androidx.test.platform.app.InstrumentationRegistry
import com.yorvana.MainActivity
import com.yorvana.testsupport.DemoMode
import com.yorvana.testsupport.ScreenshotConstants
import com.yorvana.testsupport.installFreshVault
import com.yorvana.testsupport.resetYorvanaState
import org.junit.After
import org.junit.Before
import org.junit.Rule
import java.io.File

abstract class StoreScreenshotBase {
    @get:Rule
    val composeTestRule = createAndroidComposeRule<MainActivity>()

    @Before
    fun setUpStoreScreenshot() {
        composeTestRule.resetYorvanaState()
        DemoMode.enter()
        DemoMode.ensureOutputDirectory()
        composeTestRule.installFreshVault(vaultName = "screenshots_vault") { vaultRoot ->
            copyAssetDirectory("screenshots-fixture", vaultRoot)
        }
    }

    @After
    fun tearDownStoreScreenshot() {
        DemoMode.exit()
        composeTestRule.resetYorvanaState()
    }

    protected fun captureStoreScreenshot(fileName: String) {
        composeTestRule.waitForIdle()
        val outputBucket = outputBucket()
        val outputDirectory = "${ScreenshotConstants.DEVICE_SCREENSHOT_DIR}/$outputBucket"
        val outputPath = "$outputDirectory/$fileName.png"
        DemoMode.runShell("mkdir -p $outputDirectory")
        DemoMode.runShell("screencap -p $outputPath")

        // Verify the file was captured and is non-empty
        val fileSizeResult = DemoMode.runShell("stat -c %s $outputPath").trim()
        val fileSize = fileSizeResult.toLongOrNull() ?: 0L
        check(fileSize > 0) {
            "Failed to capture store screenshot at $outputPath. File size: $fileSize. Shell output: $fileSizeResult"
        }
    }

    private fun outputBucket(): String {
        val metrics =
            InstrumentationRegistry
                .getInstrumentation()
                .targetContext.resources.displayMetrics
        val width = metrics.widthPixels
        val height = metrics.heightPixels
        val short = minOf(width, height)
        val long = maxOf(width, height)

        return when {
            // Pixel Tablet (GMD) is 1600x2560 or 2560x1600
            short >= 1600 && long >= 2560 -> "tablet-10"
            // Nexus 7 (GMD) is 1200x1920
            short >= 1200 && long >= 1920 -> "tablet-7"
            // Pixel 6 (GMD) is 1080x2400
            short >= 1080 && long >= 2400 -> "phone"
            else -> {
                Log.w("StoreScreenshot", "Unknown device dimensions: ${width}x$height. Falling back to 'phone'.")
                "phone"
            }
        }
    }

    private fun copyAssetDirectory(
        assetPath: String,
        destination: File,
    ) {
        val assets = InstrumentationRegistry.getInstrumentation().context.assets
        destination.mkdirs()
        assets.list(assetPath).orEmpty().forEach { childName ->
            val childAssetPath = if (assetPath.isEmpty()) childName else "$assetPath/$childName"
            val childDestination = File(destination, childName)

            // Try to open as a file first. If it fails, it's likely a directory.
            try {
                assets.open(childAssetPath).use { input ->
                    childDestination.outputStream().use { output ->
                        input.copyTo(output)
                    }
                }
            } catch (e: java.io.FileNotFoundException) {
                // If it's a directory, recurse. If it's truly missing, list() would have skipped it.
                copyAssetDirectory(childAssetPath, childDestination)
            }
        }
    }
}
