package de.krisenvorrat.app.domain.usecase

import de.krisenvorrat.app.domain.model.ExpiryUrgency
import org.junit.Assert.assertEquals
import org.junit.Assert.assertTrue
import org.junit.Test
import java.time.LocalDate

class GetExpiryWarningsUseCaseTest {

    private val useCase = GetExpiryWarningsUseCase()
    private val today = LocalDate.of(2026, 5, 14)

    @Test
    fun test_invoke_withItemExpiringIn3Months_returnsUrgentWarning() {
        // Given
        val items = listOf(
            buildTestItem(id = "1", expiryDate = today.plusMonths(3))
        )

        // When
        val result = useCase(items, referenceDate = today)

        // Then
        assertEquals(1, result.size)
        assertEquals(ExpiryUrgency.URGENT, result[0].urgency)
    }

    @Test
    fun test_invoke_withItemExpiringIn9Months_returnsWarning() {
        // Given
        val items = listOf(
            buildTestItem(id = "1", expiryDate = today.plusMonths(9))
        )

        // When
        val result = useCase(items, referenceDate = today)

        // Then
        assertEquals(1, result.size)
        assertEquals(ExpiryUrgency.WARNING, result[0].urgency)
    }

    @Test
    fun test_invoke_withItemExpiringIn18Months_returnsNoWarning() {
        // Given
        val items = listOf(
            buildTestItem(id = "1", expiryDate = today.plusMonths(18))
        )

        // When
        val result = useCase(items, referenceDate = today)

        // Then
        assertTrue(result.isEmpty())
    }

    @Test
    fun test_invoke_withAlreadyExpiredItem_returnsUrgentWithNegativeDays() {
        // Given
        val items = listOf(
            buildTestItem(id = "1", expiryDate = today.minusDays(10))
        )

        // When
        val result = useCase(items, referenceDate = today)

        // Then
        assertEquals(1, result.size)
        assertEquals(ExpiryUrgency.URGENT, result[0].urgency)
        assertEquals(-10L, result[0].daysUntilExpiry)
    }

    @Test
    fun test_invoke_withNoExpiryDate_skipsItem() {
        // Given
        val items = listOf(
            buildTestItem(id = "1", expiryDate = null)
        )

        // When
        val result = useCase(items, referenceDate = today)

        // Then
        assertTrue(result.isEmpty())
    }

    @Test
    fun test_invoke_withEmptyList_returnsEmptyList() {
        // Given / When
        val result = useCase(emptyList(), referenceDate = today)

        // Then
        assertTrue(result.isEmpty())
    }

    @Test
    fun test_invoke_withMixedItems_groupsByUrgency() {
        // Given
        val items = listOf(
            buildTestItem(id = "1", name = "Bald", expiryDate = today.plusMonths(2)),
            buildTestItem(id = "2", name = "Mittel", expiryDate = today.plusMonths(8)),
            buildTestItem(id = "3", name = "Weit", expiryDate = today.plusMonths(18)),
            buildTestItem(id = "4", name = "Ohne", expiryDate = null)
        )

        // When
        val result = useCase(items, referenceDate = today)

        // Then
        assertEquals(2, result.size)
        val urgent = result.filter { it.urgency == ExpiryUrgency.URGENT }
        val warning = result.filter { it.urgency == ExpiryUrgency.WARNING }
        assertEquals(1, urgent.size)
        assertEquals("Bald", urgent[0].item.name)
        assertEquals(1, warning.size)
        assertEquals("Mittel", warning[0].item.name)
    }

    @Test
    fun test_invoke_resultIsSortedByDaysUntilExpiry() {
        // Given
        val items = listOf(
            buildTestItem(id = "1", expiryDate = today.plusMonths(10)),
            buildTestItem(id = "2", expiryDate = today.plusDays(5)),
            buildTestItem(id = "3", expiryDate = today.plusMonths(4))
        )

        // When
        val result = useCase(items, referenceDate = today)

        // Then
        assertEquals(3, result.size)
        assertEquals("2", result[0].item.id)
        assertEquals("3", result[1].item.id)
        assertEquals("1", result[2].item.id)
    }

    @Test
    fun test_invoke_withItemExpiringExactlyAt6Months_isUrgent() {
        // Given
        val items = listOf(
            buildTestItem(id = "1", expiryDate = today.plusMonths(6))
        )

        // When
        val result = useCase(items, referenceDate = today)

        // Then
        assertEquals(1, result.size)
        assertEquals(ExpiryUrgency.URGENT, result[0].urgency)
    }

    @Test
    fun test_invoke_withItemExpiringExactlyAt12Months_isWarning() {
        // Given
        val items = listOf(
            buildTestItem(id = "1", expiryDate = today.plusMonths(12))
        )

        // When
        val result = useCase(items, referenceDate = today)

        // Then
        assertEquals(1, result.size)
        assertEquals(ExpiryUrgency.WARNING, result[0].urgency)
    }

    @Test
    fun test_invoke_withItemExpiringToday_isUrgentWithZeroDays() {
        // Given
        val items = listOf(
            buildTestItem(id = "1", expiryDate = today)
        )

        // When
        val result = useCase(items, referenceDate = today)

        // Then
        assertEquals(1, result.size)
        assertEquals(ExpiryUrgency.URGENT, result[0].urgency)
        assertEquals(0L, result[0].daysUntilExpiry)
    }
}
