const PAGE_MARGIN = 14
const PAGE_TOP = 12
const PAGE_BOTTOM = 22
const CONTENT_WIDTH = 210 - PAGE_MARGIN * 2
const CONTINUATION_PAGE_TOP = PAGE_MARGIN + 10
const TABLE_FONT_SIZE = 10.5
const TABLE_CELL_PADDING = 3

const formatDate = (value) => {
  if (!value) return '—'
  const parsed = new Date(value)
  if (Number.isNaN(parsed.getTime())) return value
  return new Intl.DateTimeFormat('de-DE', {
    day: '2-digit',
    month: '2-digit',
    year: 'numeric'
  }).format(parsed)
}

const sanitizeFileName = (value) =>
  (value || 'pat-test')
    .toLowerCase()
    .replace(/[^a-z0-9-_]+/gi, '-')
    .replace(/-+/g, '-')
    .replace(/^-|-$/g, '')

const formatValue = (value) => {
  if (value === '' || value === null || typeof value === 'undefined') return '—'
  return String(value)
}

const truncateText = (value, maxLength = 26) => {
  const text = String(value || '—')
  return text.length > maxLength ? `${text.slice(0, maxLength - 1)}…` : text
}

const VALUE_TABLE_LABEL = 'Versuch'

const estimateExerciseSectionHeight = (exercise) => {
  const hasSplitRows = Boolean(exercise.subA && exercise.subB)
  const valueTableHeight = hasSplitRows ? 30 : 21
  const metricsTableHeight = 21

  return 18 + valueTableHeight + metricsTableHeight
}

const buildValueTable = (exercise) => {
  if (exercise.subA && exercise.subB) {
    const valuesCount = Math.max(exercise.subA.length, exercise.subB.length)
    const headers = [VALUE_TABLE_LABEL, ...Array.from({ length: valuesCount }, (_, index) => `${index + 1}`)]
    const firstColumnWidth = 32
    const valueColumnWidth = (CONTENT_WIDTH - firstColumnWidth) / valuesCount

    return {
      head: [headers],
      body: [
        ['a.)', ...Array.from({ length: valuesCount }, (_, index) => formatValue(exercise.subA[index]))],
        ['b.)', ...Array.from({ length: valuesCount }, (_, index) => formatValue(exercise.subB[index]))]
      ],
      columnStyles: {
        0: { cellWidth: firstColumnWidth, halign: 'center' },
        ...Object.fromEntries(
          Array.from({ length: valuesCount }, (_, index) => [
            index + 1,
            { cellWidth: valueColumnWidth, halign: 'center' }
          ])
        )
      }
    }
  }

  const valuesCount = exercise.values?.length || 0
  const headers = [VALUE_TABLE_LABEL, ...Array.from({ length: valuesCount }, (_, index) => `${index + 1}`)]
  const firstColumnWidth = 32
  const valueColumnWidth = valuesCount > 0 ? (CONTENT_WIDTH - firstColumnWidth) / valuesCount : CONTENT_WIDTH - firstColumnWidth

  return {
    head: [headers],
    body: [['Ist', ...(exercise.values || []).map(formatValue)]],
    columnStyles: {
      0: { cellWidth: firstColumnWidth, halign: 'center' },
      ...Object.fromEntries(
        Array.from({ length: valuesCount }, (_, index) => [
          index + 1,
          { cellWidth: valueColumnWidth, halign: 'center' }
        ])
      )
    }
  }
}

const buildMetricsTable = (exercise) => ({
  head: [['Soll', 'Durchschnitt ist', 'Faktor', 'Punkte']],
  body: [[
    formatValue(exercise.soll),
    (exercise.durchschnitt || 0).toFixed(2),
    formatValue(exercise.faktor),
    (exercise.points || 0).toFixed(0)
  ]],
  columnStyles: {
    0: { cellWidth: CONTENT_WIDTH / 4, halign: 'center' },
    1: { cellWidth: CONTENT_WIDTH / 4, halign: 'center' },
    2: { cellWidth: CONTENT_WIDTH / 4, halign: 'center' },
    3: { cellWidth: CONTENT_WIDTH / 4, halign: 'center' }
  }
})

const buildSummaryTable = ({ assessment, totalPoints, achievement }) => ({
  head: [['Name', 'PAT Typ', 'Datum', 'Gesamtpunkte', 'Bewertung']],
  body: [[
    assessment.name || '—',
    assessment.patType || '—',
    formatDate(assessment.datum),
    String(Math.round(totalPoints || 0)),
    achievement?.name || '—'
  ]],
  columnStyles: {
    0: { cellWidth: 42 },
    1: { cellWidth: 28 },
    2: { cellWidth: 34 },
    3: { cellWidth: 34, halign: 'center' },
    4: { cellWidth: 44 }
  }
})

const buildFooterItems = ({ assessment, achievement, pageNumber, pageCount }) => ([
  `Name: ${truncateText(assessment?.name, 20)}`,
  `PAT Typ: ${truncateText(assessment?.patType, 14)}`,
  `Datum: ${formatDate(assessment?.datum)}`,
  `Bewertung: ${truncateText(achievement?.name, 18)}`,
  `Seite ${pageNumber}/${pageCount}`
])

const ensureSectionSpace = (doc, startY, minHeight) => {
  const pageHeight = doc.internal.pageSize.getHeight()
  if (startY + minHeight <= pageHeight - PAGE_BOTTOM) {
    return startY
  }

  doc.addPage()
  return CONTINUATION_PAGE_TOP
}

const drawFooter = (doc, { assessment, achievement }) => {
  const pageCount = doc.getNumberOfPages()
  const pageHeight = doc.internal.pageSize.getHeight()
  const pageWidth = doc.internal.pageSize.getWidth()
  const footerY = pageHeight - 8
  const footerXs = [
    PAGE_MARGIN,
    PAGE_MARGIN + 47,
    PAGE_MARGIN + 88,
    PAGE_MARGIN + 130,
    pageWidth - PAGE_MARGIN
  ]

  for (let pageNumber = 1; pageNumber <= pageCount; pageNumber += 1) {
    const [nameText, patTypeText, dateText, achievementText, pageText] = buildFooterItems({
      assessment,
      achievement,
      pageNumber,
      pageCount
    })

    doc.setPage(pageNumber)
    doc.setDrawColor(226, 232, 240)
    doc.setLineWidth(0.3)
    doc.line(PAGE_MARGIN, footerY - 4, pageWidth - PAGE_MARGIN, footerY - 4)
    doc.setFont('helvetica', 'normal')
    doc.setFontSize(8.5)
    doc.setTextColor(100, 116, 139)
    doc.text(nameText, footerXs[0], footerY)
    doc.text(patTypeText, footerXs[1], footerY)
    doc.text(dateText, footerXs[2], footerY)
    doc.text(achievementText, footerXs[3], footerY)
    doc.text(pageText, footerXs[4], footerY, { align: 'right' })
  }
}

export const downloadAssessmentPdf = async ({ assessment, totalPoints, achievement }) => {
  if (!assessment) return

  const [{ jsPDF }, { default: autoTable }] = await Promise.all([
    import('jspdf'),
    import('jspdf-autotable')
  ])

  const doc = new jsPDF({
    unit: 'mm',
    format: 'a4'
  })

  doc.setFillColor(16, 185, 129)
  doc.roundedRect(PAGE_MARGIN, PAGE_TOP, CONTENT_WIDTH, 18, 4, 4, 'F')
  doc.setFont('helvetica', 'bold')
  doc.setFontSize(20)
  doc.setTextColor(255, 255, 255)
  doc.text('PAT Test Details', 20, 24)

  autoTable(doc, {
    startY: 38,
    margin: { left: PAGE_MARGIN, right: PAGE_MARGIN, bottom: PAGE_BOTTOM },
    theme: 'grid',
    styles: {
      font: 'helvetica',
      fontSize: TABLE_FONT_SIZE,
      cellPadding: 4,
      textColor: [31, 41, 55],
      lineColor: [226, 232, 240],
      lineWidth: 0.3
    },
    headStyles: {
      fillColor: [241, 245, 249],
      textColor: [71, 85, 105],
      fontStyle: 'bold'
    },
    bodyStyles: {
      fillColor: [255, 255, 255]
    },
    tableWidth: CONTENT_WIDTH,
    ...buildSummaryTable({ assessment, totalPoints, achievement })
  })

  ;(assessment.exercises || []).forEach((exercise, index) => {
    const headingY = ensureSectionSpace(
      doc,
      (doc.lastAutoTable?.finalY || 38) + 8,
      estimateExerciseSectionHeight(exercise)
    )

    doc.setFont('helvetica', 'bold')
    doc.setFontSize(14)
    doc.setTextColor(17, 24, 39)
    doc.text(exercise.name || `Übung ${index + 1}`, PAGE_MARGIN, headingY)

    autoTable(doc, {
      startY: headingY + 4,
      margin: { left: PAGE_MARGIN, right: PAGE_MARGIN, bottom: PAGE_BOTTOM },
      theme: 'grid',
      styles: {
        font: 'helvetica',
        fontSize: TABLE_FONT_SIZE,
        cellPadding: TABLE_CELL_PADDING,
        halign: 'center',
        textColor: [31, 41, 55],
        lineColor: [226, 232, 240],
        lineWidth: 0.3
      },
      headStyles: {
        fillColor: [239, 246, 255],
        textColor: [30, 64, 175],
        fontStyle: 'bold',
        halign: 'center'
      },
      bodyStyles: {
        fillColor: [255, 255, 255],
        halign: 'center'
      },
      tableWidth: CONTENT_WIDTH,
      pageBreak: 'avoid',
      rowPageBreak: 'avoid',
      ...buildValueTable(exercise)
    })

    autoTable(doc, {
      startY: (doc.lastAutoTable?.finalY || headingY + 4) + 3,
      margin: { left: PAGE_MARGIN, right: PAGE_MARGIN, bottom: PAGE_BOTTOM },
      theme: 'grid',
      styles: {
        font: 'helvetica',
        fontSize: TABLE_FONT_SIZE,
        cellPadding: TABLE_CELL_PADDING,
        textColor: [31, 41, 55],
        lineColor: [226, 232, 240],
        lineWidth: 0.3
      },
      headStyles: {
        fillColor: [236, 253, 245],
        textColor: [6, 95, 70],
        fontStyle: 'bold'
      },
      bodyStyles: {
        fillColor: [255, 255, 255],
        halign: 'center'
      },
      didParseCell: ({ section, column, cell }) => {
        if (section === 'body' && column.index === 3) {
          cell.styles.fillColor = [241, 245, 249]
        }
      },
      tableWidth: CONTENT_WIDTH,
      pageBreak: 'avoid',
      rowPageBreak: 'avoid',
      ...buildMetricsTable(exercise)
    })
  })

  const fileName = [
    sanitizeFileName(assessment.name),
    sanitizeFileName(assessment.patType),
    sanitizeFileName(assessment.datum)
  ]
    .filter(Boolean)
    .join('_')

  drawFooter(doc, { assessment, achievement })
  doc.save(`${fileName || 'pat-test'}.pdf`)
}
