package de.krisenvorrat.app.domain.usecase

import org.junit.Assert.assertEquals
import org.junit.Test

class CalculateSupplyRangeUseCaseTest {

    private val useCase = CalculateSupplyRangeUseCase()

    @Test
    fun test_invoke_withKgItems_returnsCorrectDays() {
        // Given – 2 kg Reis à 3500 kcal/kg = 7000 kcal
        // 4000 kcal/Tag (2 × 2000) → 1.75 Tage
        val items = listOf(
            buildTestItem(id = "1", quantity = 2.0, unit = "kg", kcalPerKg = 3500)
        )

        // When
        val result = useCase(items, totalDailyKcal = 4000)

        // Then
        assertEquals(1.75, result, 0.001)
    }

    @Test
    fun test_invoke_withGramItems_returnsCorrectDays() {
        // Given – 500 g Nudeln à 3600 kcal/kg = 1800 kcal
        // 2000 kcal/Tag → 0.9 Tage
        val items = listOf(
            buildTestItem(id = "1", quantity = 500.0, unit = "g", kcalPerKg = 3600)
        )

        // When
        val result = useCase(items, totalDailyKcal = 2000)

        // Then
        assertEquals(0.9, result, 0.001)
    }

    @Test
    fun test_invoke_withMultipleItems_sumsTotalKcal() {
        // Given – 1 kg Reis (3500 kcal/kg = 3500 kcal) + 500 g Nudeln (3600 kcal/kg = 1800 kcal) = 5300 kcal
        // 4000 kcal/Tag → 1.325 Tage
        val items = listOf(
            buildTestItem(id = "1", quantity = 1.0, unit = "kg", kcalPerKg = 3500),
            buildTestItem(id = "2", quantity = 500.0, unit = "g", kcalPerKg = 3600)
        )

        // When
        val result = useCase(items, totalDailyKcal = 4000)

        // Then
        assertEquals(1.325, result, 0.001)
    }

    @Test
    fun test_invoke_withEmptyList_returnsZero() {
        // Given / When
        val result = useCase(emptyList(), totalDailyKcal = 4000)

        // Then
        assertEquals(0.0, result, 0.001)
    }

    @Test
    fun test_invoke_withNullKcal_skipsItem() {
        // Given – Item ohne kcalPerKg wird ignoriert
        val items = listOf(
            buildTestItem(id = "1", quantity = 1.0, unit = "kg", kcalPerKg = null),
            buildTestItem(id = "2", quantity = 1.0, unit = "kg", kcalPerKg = 2000)
        )

        // When – Nur 1 kg à 2000 kcal/kg = 2000 kcal, 2000 kcal/Tag = 1.0 Tage
        val result = useCase(items, totalDailyKcal = 2000)

        // Then
        assertEquals(1.0, result, 0.001)
    }

    @Test
    fun test_invoke_withNonWeightUnit_skipsItem() {
        // Given – "Stk" ist keine Gewichtseinheit → wird ignoriert
        val items = listOf(
            buildTestItem(id = "1", quantity = 5.0, unit = "Stk", kcalPerKg = 2000)
        )

        // When
        val result = useCase(items, totalDailyKcal = 4000)

        // Then
        assertEquals(0.0, result, 0.001)
    }

    @Test
    fun test_invoke_withZeroTotalDailyKcal_returnsZero() {
        // Given
        val items = listOf(
            buildTestItem(id = "1", quantity = 1.0, unit = "kg", kcalPerKg = 3500)
        )

        // When
        val result = useCase(items, totalDailyKcal = 0)

        // Then
        assertEquals(0.0, result, 0.001)
    }

    @Test
    fun test_invoke_withDefaultParameters_uses4000KcalPerDay() {
        // Given – 4 kg Reis à 3500 kcal/kg = 14000 kcal
        // Default: 4000 kcal/Tag → 3.5 Tage
        val items = listOf(
            buildTestItem(id = "1", quantity = 4.0, unit = "kg", kcalPerKg = 3500)
        )

        // When
        val result = useCase(items)

        // Then
        assertEquals(3.5, result, 0.001)
    }

    @Test
    fun test_invoke_withMgUnit_convertsCorrectly() {
        // Given – 500000 mg = 500 g à 2000 kcal/kg = 1000 kcal
        // 1000 kcal/Tag → 1.0 Tag
        val items = listOf(
            buildTestItem(id = "1", quantity = 500000.0, unit = "mg", kcalPerKg = 2000)
        )

        // When
        val result = useCase(items, totalDailyKcal = 1000)

        // Then
        assertEquals(1.0, result, 0.001)
    }

    @Test
    fun test_invoke_withMixedUnits_onlyCountsWeightBased() {
        // Given – 1 kg (3500 kcal/kg) + 5 Stk (ignored) + 2 L (ignored)
        // Total: 3500 kcal, 2000 kcal/Tag → 1.75 Tage
        val items = listOf(
            buildTestItem(id = "1", quantity = 1.0, unit = "kg", kcalPerKg = 3500),
            buildTestItem(id = "2", quantity = 5.0, unit = "Stk", kcalPerKg = 1000),
            buildTestItem(id = "3", quantity = 2.0, unit = "L", kcalPerKg = 450)
        )

        // When
        val result = useCase(items, totalDailyKcal = 2000)

        // Then
        assertEquals(1.75, result, 0.001)
    }
}
