package com.yorvana.testsupport

import android.content.ContentValues
import android.content.Context
import android.net.Uri
import android.os.Build
import android.provider.MediaStore
import androidx.test.platform.app.InstrumentationRegistry
import org.junit.rules.ExternalResource
import java.io.File
import java.util.UUID

const val TINY_PDF_ASSET = "test_receipt.pdf"
const val TINY_PDF_SHA256 = "3ef3c4cfaf67c8018211edf7b5a9bbfa233d6d8c86ab99f1986d7c61b0e44201"

class FixtureAssetsRule : ExternalResource() {
    private val targetContext: Context = InstrumentationRegistry.getInstrumentation().targetContext
    private val testContext: Context = InstrumentationRegistry.getInstrumentation().context
    private val resolver = targetContext.contentResolver
    private val mediaStoreUris = mutableListOf<Uri>()
    private val cacheFiles = mutableListOf<File>()

    override fun after() {
        mediaStoreUris.forEach { resolver.delete(it, null, null) }
        cacheFiles.forEach { it.delete() }
        mediaStoreUris.clear()
        cacheFiles.clear()
    }

    fun copyToCache(assetName: String): File {
        val target = File(targetContext.cacheDir, assetName)
        cacheFiles += target
        testContext.assets.open(assetName).use { input ->
            target.outputStream().use { output -> input.copyTo(output) }
        }
        return target
    }

    fun copyToDownloads(
        assetName: String,
        displayName: String = assetName,
        mimeType: String = mimeTypeFor(assetName),
    ): Uri {
        val values =
            ContentValues().apply {
                put(MediaStore.Downloads.DISPLAY_NAME, displayName)
                put(MediaStore.Downloads.MIME_TYPE, mimeType)
                if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
                    put(MediaStore.Downloads.IS_PENDING, 1)
                }
            }
        val uri =
            resolver.insert(MediaStore.Downloads.EXTERNAL_CONTENT_URI, values)
                ?: error("Unable to create Downloads fixture: $displayName")
        mediaStoreUris += uri
        testContext.assets.open(assetName).use { input ->
            resolver.openOutputStream(uri)?.use { output -> input.copyTo(output) }
                ?: error("Unable to write Downloads fixture: $displayName")
        }
        if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.Q) {
            resolver.update(
                uri,
                ContentValues().apply { put(MediaStore.Downloads.IS_PENDING, 0) },
                null,
                null,
            )
        }
        return uri
    }

    fun copyUniquePdfToDownloads(scenarioId: String): DownloadFixture {
        val displayName = "yorvana-fixture-$scenarioId-${UUID.randomUUID()}.pdf"
        val uri = copyToDownloads(TINY_PDF_ASSET, displayName, "application/pdf")
        return DownloadFixture(uri = uri, displayName = displayName, sha256 = TINY_PDF_SHA256)
    }

    private fun mimeTypeFor(assetName: String): String =
        when (assetName.substringAfterLast('.', missingDelimiterValue = "").lowercase()) {
            "jpg", "jpeg" -> "image/jpeg"
            "pdf" -> "application/pdf"
            else -> "application/octet-stream"
        }
}

data class DownloadFixture(
    val uri: Uri,
    val displayName: String,
    val sha256: String,
)
