package com.tt.honeyDue.notifications

import android.app.NotificationManager
import android.content.Context
import android.os.Build
import androidx.test.core.app.ApplicationProvider
import com.google.firebase.messaging.RemoteMessage
import org.junit.Assert.assertEquals
import org.junit.Assert.assertNotNull
import org.junit.Assert.assertTrue
import org.junit.Before
import org.junit.Test
import org.junit.runner.RunWith
import org.robolectric.Robolectric
import org.robolectric.RobolectricTestRunner
import org.robolectric.annotation.Config

/**
 * Tests for [FcmService] — verify channel routing and deep-link handling
 * when data messages arrive.
 */
@RunWith(RobolectricTestRunner::class)
@Config(sdk = [Build.VERSION_CODES.TIRAMISU])
class FcmServiceTest {

    private lateinit var context: Context
    private lateinit var manager: NotificationManager
    private lateinit var service: FcmService

    @Before
    fun setUp() {
        context = ApplicationProvider.getApplicationContext()
        manager = context.getSystemService(Context.NOTIFICATION_SERVICE) as NotificationManager
        manager.notificationChannels.forEach { manager.deleteNotificationChannel(it.id) }
        manager.cancelAll()
        service = Robolectric.setupService(FcmService::class.java)
    }

    private fun remoteMessage(id: String, data: Map<String, String>): RemoteMessage {
        val b = RemoteMessage.Builder("test@fcm")
        b.setMessageId(id)
        data.forEach { (k, v) -> b.addData(k, v) }
        return b.build()
    }

    @Test
    fun onMessageReceived_routesTaskReminder_toCorrectChannel() {
        val msg = remoteMessage(
            id = "m-1",
            data = mapOf(
                "type" to "task_reminder",
                "task_id" to "7",
                "title" to "Reminder",
                "body" to "Do it"
            )
        )

        service.onMessageReceived(msg)

        // Channel must have been created and a notification posted on it.
        val channel = manager.getNotificationChannel(NotificationChannels.TASK_REMINDER)
        assertNotNull("task_reminder channel should be created", channel)

        val posted = manager.activeNotifications
        assertTrue("one notification should be posted", posted.isNotEmpty())
        val n = posted.first()
        assertEquals(NotificationChannels.TASK_REMINDER, n.notification.channelId)
    }

    @Test
    fun onMessageReceived_routesTaskOverdue_toHighChannel() {
        val msg = remoteMessage(
            id = "m-2",
            data = mapOf(
                "type" to "task_overdue",
                "task_id" to "8",
                "title" to "Overdue",
                "body" to "Late"
            )
        )

        service.onMessageReceived(msg)

        val posted = manager.activeNotifications
        assertTrue(posted.isNotEmpty())
        assertEquals(NotificationChannels.TASK_OVERDUE, posted.first().notification.channelId)
    }

    @Test
    fun onMessageReceived_routesResidenceInvite() {
        val msg = remoteMessage(
            id = "m-3",
            data = mapOf(
                "type" to "residence_invite",
                "residence_id" to "42",
                "title" to "Invite",
                "body" to "Join us"
            )
        )

        service.onMessageReceived(msg)

        val posted = manager.activeNotifications
        assertTrue(posted.isNotEmpty())
        assertEquals(NotificationChannels.RESIDENCE_INVITE, posted.first().notification.channelId)
    }

    @Test
    fun onMessageReceived_routesSubscription_toLowChannel() {
        val msg = remoteMessage(
            id = "m-4",
            data = mapOf(
                "type" to "subscription",
                "title" to "Sub",
                "body" to "Changed"
            )
        )

        service.onMessageReceived(msg)

        val posted = manager.activeNotifications
        assertTrue(posted.isNotEmpty())
        assertEquals(NotificationChannels.SUBSCRIPTION, posted.first().notification.channelId)
    }

    @Test
    fun onMessageReceived_withTaskId_sets_deep_link() {
        val msg = remoteMessage(
            id = "m-5",
            data = mapOf(
                "type" to "task_reminder",
                "task_id" to "123",
                "title" to "T",
                "body" to "B",
                "deep_link" to "honeydue://task/123"
            )
        )

        service.onMessageReceived(msg)

        val posted = manager.activeNotifications
        assertTrue(posted.isNotEmpty())
        val contentIntent = posted.first().notification.contentIntent
        assertNotNull("content intent should be attached for deep-link tap", contentIntent)
    }

    @Test
    fun onMessageReceived_malformedPayload_postsNothing() {
        // Missing type → payload parse returns null → nothing posted.
        val msg = remoteMessage(
            id = "m-6",
            data = mapOf(
                "title" to "x",
                "body" to "y"
            )
        )

        service.onMessageReceived(msg)

        assertTrue(
            "no notification should be posted for malformed payload",
            manager.activeNotifications.isEmpty()
        )
    }

    @Test
    fun onMessageReceived_distinctMessageIds_produceDistinctNotifications() {
        service.onMessageReceived(
            remoteMessage(
                "id-A",
                mapOf("type" to "task_reminder", "task_id" to "1", "title" to "A", "body" to "a")
            )
        )
        service.onMessageReceived(
            remoteMessage(
                "id-B",
                mapOf("type" to "task_reminder", "task_id" to "2", "title" to "B", "body" to "b")
            )
        )

        assertEquals(2, manager.activeNotifications.size)
    }
}
