package de.krisenvorrat.app.data.export

import android.graphics.Paint
import android.graphics.Typeface
import android.graphics.pdf.PdfDocument
import de.krisenvorrat.app.data.db.entity.CategoryEntity
import de.krisenvorrat.app.data.db.entity.ItemEntity
import de.krisenvorrat.app.data.db.entity.LocationEntity
import java.io.File
import java.io.FileOutputStream
import java.time.LocalDate
import java.time.format.DateTimeFormatter
import java.util.Locale

internal object PdfExporter {

    private const val PAGE_WIDTH = 595  // A4
    private const val PAGE_HEIGHT = 842 // A4
    private const val MARGIN_LEFT = 40f
    private const val MARGIN_TOP = 50f
    private const val MARGIN_BOTTOM = 40f
    private const val LINE_HEIGHT = 18f
    private const val HEADER_HEIGHT = 28f

    private val DATE_FORMATTER = DateTimeFormatter.ofPattern("dd.MM.yyyy", Locale.GERMAN)

    fun export(
        file: File,
        items: List<ItemEntity>,
        categories: List<CategoryEntity>,
        locations: List<LocationEntity>
    ) {
        val locationMap = locations.associate { it.id to it.name }
        val document = PdfDocument()
        var pageNumber = 1
        var pageInfo = PdfDocument.PageInfo.Builder(PAGE_WIDTH, PAGE_HEIGHT, pageNumber).create()
        var page = document.startPage(pageInfo)
        var canvas = page.canvas
        var yPos = MARGIN_TOP

        val titlePaint = Paint().apply {
            textSize = 18f
            typeface = Typeface.create(Typeface.DEFAULT, Typeface.BOLD)
            isAntiAlias = true
        }
        val categoryPaint = Paint().apply {
            textSize = 14f
            typeface = Typeface.create(Typeface.DEFAULT, Typeface.BOLD)
            isAntiAlias = true
        }
        val headerPaint = Paint().apply {
            textSize = 10f
            typeface = Typeface.create(Typeface.DEFAULT, Typeface.BOLD)
            isAntiAlias = true
        }
        val textPaint = Paint().apply {
            textSize = 10f
            isAntiAlias = true
        }
        val smallPaint = Paint().apply {
            textSize = 8f
            color = 0xFF666666.toInt()
            isAntiAlias = true
        }

        // Title
        canvas.drawText("Krisenvorrat Inventar", MARGIN_LEFT, yPos, titlePaint)
        yPos += 8f
        canvas.drawText(
            "Erstellt am ${LocalDate.now().format(DATE_FORMATTER)}",
            MARGIN_LEFT, yPos + LINE_HEIGHT, smallPaint
        )
        yPos += HEADER_HEIGHT + LINE_HEIGHT

        // Column positions
        val colName = MARGIN_LEFT
        val colQty = 250f
        val colUnit = 300f
        val colExpiry = 350f
        val colLocation = 420f
        val colPrice = 500f

        var totalValue = 0.0

        for (category in categories) {
            val categoryItems = items.filter { it.categoryId == category.id }
            if (categoryItems.isEmpty()) continue

            // Check if we need a new page for category header + at least one item
            if (yPos + HEADER_HEIGHT + LINE_HEIGHT * 2 > PAGE_HEIGHT - MARGIN_BOTTOM) {
                document.finishPage(page)
                pageNumber++
                pageInfo = PdfDocument.PageInfo.Builder(PAGE_WIDTH, PAGE_HEIGHT, pageNumber).create()
                page = document.startPage(pageInfo)
                canvas = page.canvas
                yPos = MARGIN_TOP
            }

            // Category header
            yPos += 6f
            canvas.drawText(category.name, MARGIN_LEFT, yPos, categoryPaint)
            yPos += HEADER_HEIGHT

            // Table header
            canvas.drawText("Name", colName, yPos, headerPaint)
            canvas.drawText("Menge", colQty, yPos, headerPaint)
            canvas.drawText("Einheit", colUnit, yPos, headerPaint)
            canvas.drawText("MHD", colExpiry, yPos, headerPaint)
            canvas.drawText("Lagerort", colLocation, yPos, headerPaint)
            canvas.drawText("Preis", colPrice, yPos, headerPaint)
            yPos += 4f
            canvas.drawLine(MARGIN_LEFT, yPos, PAGE_WIDTH - MARGIN_LEFT, yPos, textPaint)
            yPos += LINE_HEIGHT

            for (item in categoryItems) {
                if (yPos + LINE_HEIGHT > PAGE_HEIGHT - MARGIN_BOTTOM) {
                    document.finishPage(page)
                    pageNumber++
                    pageInfo = PdfDocument.PageInfo.Builder(PAGE_WIDTH, PAGE_HEIGHT, pageNumber).create()
                    page = document.startPage(pageInfo)
                    canvas = page.canvas
                    yPos = MARGIN_TOP
                }

                val itemValue = item.quantity * item.unitPrice
                totalValue += itemValue

                canvas.drawText(truncate(item.name, 30), colName, yPos, textPaint)
                canvas.drawText(formatQuantity(item.quantity), colQty, yPos, textPaint)
                canvas.drawText(item.unit, colUnit, yPos, textPaint)
                canvas.drawText(item.expiryDate?.format(DATE_FORMATTER) ?: "–", colExpiry, yPos, textPaint)
                canvas.drawText(truncate(locationMap[item.locationId] ?: "–", 15), colLocation, yPos, textPaint)
                canvas.drawText(formatPrice(itemValue), colPrice, yPos, textPaint)
                yPos += LINE_HEIGHT
            }
        }

        // Total value
        yPos += LINE_HEIGHT
        if (yPos + LINE_HEIGHT * 2 > PAGE_HEIGHT - MARGIN_BOTTOM) {
            document.finishPage(page)
            pageNumber++
            pageInfo = PdfDocument.PageInfo.Builder(PAGE_WIDTH, PAGE_HEIGHT, pageNumber).create()
            page = document.startPage(pageInfo)
            canvas = page.canvas
            yPos = MARGIN_TOP
        }
        canvas.drawLine(MARGIN_LEFT, yPos, PAGE_WIDTH - MARGIN_LEFT, yPos, textPaint)
        yPos += LINE_HEIGHT
        canvas.drawText("Gesamtwert: ${formatPrice(totalValue)} €", MARGIN_LEFT, yPos, categoryPaint)

        document.finishPage(page)

        FileOutputStream(file).use { out ->
            document.writeTo(out)
        }
        document.close()
    }

    private fun truncate(text: String, maxLength: Int): String {
        return if (text.length > maxLength) text.take(maxLength - 1) + "…" else text
    }

    private fun formatQuantity(value: Double): String {
        return if (value == value.toLong().toDouble()) {
            value.toLong().toString()
        } else {
            String.format(Locale.GERMAN, "%.1f", value)
        }
    }

    private fun formatPrice(value: Double): String {
        return String.format(Locale.GERMAN, "%.2f", value)
    }
}
