package de.tsschulz.tt_tagebuch.app.pdf

import android.graphics.Canvas
import android.graphics.Color
import android.graphics.Paint
import android.graphics.Typeface
import android.graphics.pdf.PdfDocument
import android.text.Layout
import android.text.StaticLayout
import android.text.TextPaint
import de.tsschulz.tt_tagebuch.shared.api.models.Member
import de.tsschulz.tt_tagebuch.shared.api.models.MemberContactDto
import java.io.File
import java.io.FileOutputStream
import java.time.LocalDate
import java.time.format.DateTimeFormatter
import java.util.Locale

private const val PAGE_W = 595
private const val PAGE_H = 842
private const val MARGIN = 40f
private const val MAX_TEXT_W = (PAGE_W - MARGIN * 2).toInt()

private fun newTitlePaint(): TextPaint = TextPaint(Paint.ANTI_ALIAS_FLAG).apply {
    color = Color.BLACK
    textSize = 14f
    typeface = Typeface.create(Typeface.DEFAULT, Typeface.BOLD)
}

private fun newBodyPaint(): TextPaint = TextPaint(Paint.ANTI_ALIAS_FLAG).apply {
    color = Color.BLACK
    textSize = 10f
    typeface = Typeface.create(Typeface.DEFAULT, Typeface.NORMAL)
    textLocale = Locale.GERMANY
}

private fun newBoldPaint(): TextPaint = TextPaint(Paint.ANTI_ALIAS_FLAG).apply {
    color = Color.BLACK
    textSize = 10f
    typeface = Typeface.create(Typeface.DEFAULT, Typeface.BOLD)
    textLocale = Locale.GERMANY
}

private fun Canvas.drawStatic(text: String, paint: TextPaint, x: Float, y: Float): Float {
    if (text.isEmpty()) return y
    val layout = StaticLayout.Builder.obtain(text, 0, text.length, paint, MAX_TEXT_W)
        .setAlignment(Layout.Alignment.ALIGN_NORMAL)
        .setLineSpacing(0f, 1.05f)
        .setIncludePad(false)
        .build()
    save()
    translate(x, y)
    layout.draw(this)
    restore()
    return y + layout.height + 4f
}

private fun formatBirthDe(birthDate: String?): String {
    if (birthDate.isNullOrBlank()) return ""
    val day = birthDate.trim().take(10)
    val d = runCatching { LocalDate.parse(day) }.getOrNull() ?: return ""
    return d.format(DateTimeFormatter.ofPattern("dd.MM.yyyy", Locale.GERMANY))
}

private data class PhoneLine(val value: String, val label: String?)

private fun memberPhoneLines(member: Member): List<PhoneLine> {
    val phones = member.contacts
        .filter { it.type == "phone" && it.value.isNotBlank() }
        .sortedWith(compareBy<MemberContactDto> { !it.isPrimary }.thenBy { it.id ?: 0 })
    val out = phones.map { c ->
        val v = c.value.trim()
        val suffix = if (c.isParent) {
            val p = c.parentName?.trim().orEmpty()
            if (p.isNotEmpty()) " ($p)" else " (Eltern)"
        } else {
            ""
        }
        PhoneLine(v + suffix, null)
    }.toMutableList()
    val legacy = member.phone?.trim().orEmpty()
    if (out.isEmpty() && legacy.isNotEmpty()) {
        out.add(PhoneLine(legacy, null))
    }
    return out
}

/**
 * Telefonliste wie Web-[PDFGenerator.addPhoneList]: Name, Geburtsdatum, Telefonnummern.
 */
fun writeMembersPhoneListPdf(
    outFile: File,
    titleLine: String,
    members: List<Member>,
) {
    val sorted = members.sortedWith(
        compareBy<Member> { it.lastName.lowercase(Locale.GERMANY) }.thenBy { it.firstName.lowercase(Locale.GERMANY) },
    )
    val doc = PdfDocument()
    var pageSeq = 0
    fun openPage(): PdfDocument.Page {
        pageSeq++
        return doc.startPage(PdfDocument.PageInfo.Builder(PAGE_W, PAGE_H, pageSeq).create())
    }
    var page = openPage()
    var canvas = page.canvas
    var y = MARGIN
    val titlePaint = newTitlePaint()
    val bodyPaint = newBodyPaint()
    val boldPaint = newBoldPaint()

    fun newPageIfNeeded(extra: Float) {
        if (y + extra > PAGE_H - MARGIN) {
            doc.finishPage(page)
            page = openPage()
            canvas = page.canvas
            y = MARGIN
        }
    }

    y = canvas.drawStatic(titleLine, titlePaint, MARGIN, y)
    y = canvas.drawStatic("", bodyPaint, MARGIN, y)
    y = canvas.drawStatic("Name, Vorname", boldPaint, MARGIN, y)
    y = canvas.drawStatic("Geburtsdatum / Telefon", bodyPaint, MARGIN, y)
    y = canvas.drawStatic("—".repeat(42), bodyPaint, MARGIN, y)

    for (member in sorted) {
        val phones = memberPhoneLines(member)
        val nameLine = "${member.lastName}, ${member.firstName}".trim()
        val birth = formatBirthDe(member.birthDate)
        val blockHeight = 18f + phones.size.coerceAtLeast(1) * 14f
        newPageIfNeeded(blockHeight)
        y = canvas.drawStatic(nameLine, boldPaint, MARGIN, y)
        val sub = buildString {
            if (birth.isNotEmpty()) append("Geboren: $birth")
            if (phones.isEmpty()) {
                if (isNotEmpty()) append(" — ")
                append("—")
            }
        }
        y = canvas.drawStatic(sub, bodyPaint, MARGIN, y)
        if (phones.isEmpty()) {
            y += 4f
        } else {
            for (p in phones) {
                newPageIfNeeded(16f)
                y = canvas.drawStatic("Tel.: ${p.value}", bodyPaint, MARGIN + 12f, y)
            }
        }
        y = canvas.drawStatic("", bodyPaint, MARGIN, y)
    }

    doc.finishPage(page)
    FileOutputStream(outFile).use { doc.writeTo(it) }
    doc.close()
}
