package de.krisenvorrat.app.data.export

import de.krisenvorrat.app.data.db.entity.CategoryEntity
import de.krisenvorrat.app.data.db.entity.LocationEntity
import org.junit.Assert.assertEquals
import org.junit.Assert.assertTrue
import org.junit.Test
import java.time.LocalDate

class CsvExporterTest {

    @Test
    fun test_export_withItems_producesCorrectCsv() {
        // Given
        val categories = listOf(CategoryEntity(id = 1, name = "Lebensmittel"))
        val locations = listOf(LocationEntity(id = 1, name = "Keller"))
        val items = listOf(
            buildItemEntity("item1").copy(
                name = "Konserve",
                quantity = 5.0,
                unit = "Stk",
                unitPrice = 1.50,
                kcalPerKg = 800,
                expiryDate = LocalDate.of(2027, 3, 15),
                locationId = 1
            )
        )

        // When
        val csv = CsvExporter.export(items, categories, locations)

        // Then
        assertTrue(csv.startsWith("\uFEFF"))
        val lines = csv.lines().filter { it.isNotBlank() }
        assertEquals(2, lines.size)
        assertEquals("\uFEFFName;Kategorie;Menge;Einheit;Stückpreis;kcal/kg;MHD;Lagerort;Notizen", lines[0])
        assertEquals("Konserve;Lebensmittel;5;Stk;1,50;800;15.03.2027;Keller;", lines[1])
    }

    @Test
    fun test_export_withSemicolonInField_escapesCorrectly() {
        // Given
        val categories = listOf(CategoryEntity(id = 1, name = "Test"))
        val locations = listOf(LocationEntity(id = 1, name = "Keller"))
        val items = listOf(
            buildItemEntity("item1").copy(name = "Reis; Langkorn")
        )

        // When
        val csv = CsvExporter.export(items, categories, locations)

        // Then
        assertTrue(csv.contains("\"Reis; Langkorn\""))
    }

    @Test
    fun test_export_withQuoteInField_doublesQuotes() {
        // Given
        val categories = listOf(CategoryEntity(id = 1, name = "Test"))
        val locations = listOf(LocationEntity(id = 1, name = "Keller"))
        val items = listOf(
            buildItemEntity("item1").copy(notes = "Marke \"Premium\"")
        )

        // When
        val csv = CsvExporter.export(items, categories, locations)

        // Then
        assertTrue(csv.contains("\"Marke \"\"Premium\"\"\""))
    }

    @Test
    fun test_export_withNoExpiryDate_emptyField() {
        // Given
        val categories = listOf(CategoryEntity(id = 1, name = "Test"))
        val locations = listOf(LocationEntity(id = 1, name = "Keller"))
        val items = listOf(
            buildItemEntity("item1").copy(expiryDate = null)
        )

        // When
        val csv = CsvExporter.export(items, categories, locations)

        // Then
        val dataLine = csv.lines()[1]
        val fields = dataLine.split(";")
        // MHD is the 7th field (index 6)
        assertEquals("", fields[6])
    }

    @Test
    fun test_export_withNoItems_headerOnly() {
        // Given
        val csv = CsvExporter.export(emptyList(), emptyList(), emptyList())

        // Then
        assertTrue(csv.startsWith("\uFEFF"))
        val lines = csv.lines().filter { it.isNotBlank() }
        assertEquals(1, lines.size)
    }

    @Test
    fun test_export_withUnknownCategory_emptyName() {
        // Given
        val categories = listOf(CategoryEntity(id = 1, name = "Lebensmittel"))
        val locations = listOf(LocationEntity(id = 1, name = "Keller"))
        val items = listOf(
            buildItemEntity("item1").copy(categoryId = 99)
        )

        // When
        val csv = CsvExporter.export(items, categories, locations)

        // Then
        val dataLine = csv.lines()[1]
        val fields = dataLine.split(";")
        // Category is the 2nd field (index 1)
        assertEquals("", fields[1])
    }

    @Test
    fun test_export_withFractionalQuantity_usesGermanComma() {
        // Given
        val categories = listOf(CategoryEntity(id = 1, name = "Test"))
        val locations = listOf(LocationEntity(id = 1, name = "Keller"))
        val items = listOf(
            buildItemEntity("item1").copy(quantity = 2.5)
        )

        // When
        val csv = CsvExporter.export(items, categories, locations)

        // Then
        assertTrue(csv.contains("2,5"))
    }
}
