package com.yorvana.util

import android.content.Context
import com.yorvana.BuildConfig
import io.mockk.every
import io.mockk.mockk
import io.mockk.mockkStatic
import io.mockk.unmockkAll
import io.mockk.verify
import io.mockk.verifyOrder
import io.sentry.Sentry
import io.sentry.android.core.SentryAndroid
import io.sentry.android.core.SentryAndroidOptions
import org.junit.After
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.robolectric.RobolectricTestRunner
import org.robolectric.annotation.Config

@RunWith(RobolectricTestRunner::class)
@Config(sdk = [34])
class SentryWrapperTest {
    private lateinit var context: Context
    private val params = mockk<SentryInitParams>(relaxed = true)
    private val wrapper = SentryWrapperImpl(params)

    @Before
    fun setUp() {
        context = mockk(relaxed = true)
        mockkStatic(Sentry::class)
        mockkStatic(SentryAndroid::class)
    }

    @After
    fun tearDown() {
        unmockkAll()
    }

    @Test
    fun `captureFeedback should set tags and capture user feedback`() {
        val comments = "Test comments"
        val email = "test@example.com"
        val tags = mapOf("key" to "value")
        val scope = mockk<io.sentry.IScope>(relaxed = true)

        every { Sentry.withScope(any()) } answers {
            val callback = firstArg<io.sentry.ScopeCallback>()
            callback.run(scope)
        }

        wrapper.captureFeedback(comments, email, tags)

        verify {
            Sentry.withScope(any())
            scope.setTag("key", "value")
            Sentry.captureUserFeedback(
                match {
                    it.comments == comments && it.email == email
                },
            )
        }
    }

    @Test
    fun `lazyInitAndSendFeedback should init Sentry, send feedback, flush and close`() {
        val release = "${BuildConfig.APPLICATION_ID}@${BuildConfig.VERSION_NAME}+${BuildConfig.VERSION_CODE}"
        val feedbackParams =
            SentryInitParams(
                "https://dsn@sentry.io/1",
                "debug",
                release,
            )
        val wrapperWithParams = SentryWrapperImpl(feedbackParams)
        val comments = "Test comments"
        val email = "test@example.com"
        val tags = mapOf("key" to "value")

        val options = mockk<SentryAndroidOptions>(relaxed = true)
        every { options.shutdownTimeoutMillis = any() } returns Unit
        every { options.shutdownTimeoutMillis } returns 5_000L

        // Mock SentryAndroid.init to capture options and run the configuration block
        every { SentryAndroid.init(any<Context>(), any<Sentry.OptionsConfiguration<SentryAndroidOptions>>()) } answers {
            val config = secondArg<Sentry.OptionsConfiguration<SentryAndroidOptions>>()
            config.configure(options)
        }

        wrapperWithParams.lazyInitAndSendFeedback(context, comments, email, tags)

        verifyOrder {
            SentryAndroid.init(any<Context>(), any<Sentry.OptionsConfiguration<SentryAndroidOptions>>())
            Sentry.addBreadcrumb(
                match<String> {
                    it.contains("User-initiated feedback submission")
                },
            )
            Sentry.flush(5_000L)
            Sentry.close()
        }
        verify { options.environment = "debug" }
        verify { options.release = release }
    }
}
