package com.yorvana.testsupport

import androidx.test.ext.junit.runners.AndroidJUnit4
import androidx.test.platform.app.InstrumentationRegistry
import androidx.test.uiautomator.UiDevice
import com.yorvana.testsupport.tiers.Smoke
import org.junit.Assert.assertEquals
import org.junit.Assert.assertTrue
import org.junit.Test
import org.junit.runner.Description
import org.junit.runner.RunWith
import org.junit.runners.model.Statement

@RunWith(AndroidJUnit4::class)
@Smoke
class RetryRuleTest {
    @Test
    fun testRetryRuleWritesFlakeMarkerOnFlakyTest() {
        val rule = RetryRule(maxRetries = 2)
        val description =
            Description.createTestDescription(
                "com.yorvana.testsupport.RetryRuleTest",
                "dummyFlakyTest",
            )

        val outputDir = "/data/local/tmp/flakes"
        val expectedMarkerFile = "$outputDir/flake-com.yorvana.testsupport.RetryRuleTest_dummyFlakyTest.txt"

        // Clean up first
        deleteFile(expectedMarkerFile)

        var callCount = 0
        val baseStatement =
            object : Statement() {
                override fun evaluate() {
                    callCount++
                    if (callCount == 1) {
                        throw RuntimeException("Simulated failure")
                    }
                    // Second call passes
                }
            }

        val wrapped = rule.apply(baseStatement, description)
        wrapped.evaluate()

        assertEquals(2, callCount)

        assertTrue("Flake marker file should exist on device", fileExists(expectedMarkerFile))

        // Clean up after test
        deleteFile(expectedMarkerFile)
    }

    private fun fileExists(path: String): Boolean {
        val output = runShell("ls $path")
        return output.trim().isNotEmpty() && !output.contains("No such file or directory")
    }

    private fun deleteFile(path: String) {
        runShell("rm -f $path")
    }

    private fun runShell(command: String): String {
        val instrumentation = InstrumentationRegistry.getInstrumentation()
        val device = UiDevice.getInstance(instrumentation)
        return device.executeShellCommand(command)
    }
}
