package pl.firmatpp.kierowca.diagnostics

import org.junit.After
import org.junit.Assert.assertEquals
import org.junit.Assert.assertSame
import org.junit.Test

class AppDiagnosticsTest {
    private val sink = RecordingDiagnosticsSink()

    @After
    fun tearDown() {
        AppDiagnostics.installSink(NoOpDiagnosticsSink)
    }

    @Test
    fun reportNonFatalAddsOperationContextBeforeRecordingException() {
        AppDiagnostics.installSink(sink)
        val throwable = IllegalStateException("upload failed")

        AppDiagnostics.reportNonFatal(
            throwable = throwable,
            operation = "photo_upload",
            keys = mapOf("route_id" to "R-42", "retryable" to true),
        )

        assertEquals(
            listOf(
                "key:operation=photo_upload",
                "key:route_id=R-42",
                "key:retryable=true",
                "log:non_fatal: photo_upload: upload failed",
                "exception:IllegalStateException",
            ),
            sink.events,
        )
        assertSame(throwable, sink.throwables.single())
    }

    @Test
    fun clearDriverIdClearsPreviouslySetUserIdentifier() {
        AppDiagnostics.installSink(sink)

        AppDiagnostics.setDriverId("driver-7")
        AppDiagnostics.clearDriverId()

        assertEquals(listOf("user:driver-7", "user:"), sink.events)
    }

    private class RecordingDiagnosticsSink : DiagnosticsSink {
        val events = mutableListOf<String>()
        val throwables = mutableListOf<Throwable>()

        override fun log(message: String) {
            events += "log:$message"
        }

        override fun setUserId(userId: String) {
            events += "user:$userId"
        }

        override fun setCustomKey(key: String, value: String) {
            events += "key:$key=$value"
        }

        override fun recordException(throwable: Throwable) {
            events += "exception:${throwable::class.simpleName}"
            throwables += throwable
        }
    }
}
