// Shared CSV mechanics for exporting marketplace settlement data into lexoffice's
// manual electronic-Kontoauszug (bank statement) CSV import — used by the Amazon
// and eBay settlement pages. Format confirmed against lexoffice's own
// reference/banking-lexoffice/Bankimport-Vorlage.csv template + their CSV-import
// help article: semicolon-delimited, DD.MM.YYYY dates (other formats are
// rejected), German-comma amounts, no currency symbol, no quoting (the real
// template has none), and — critically — a cell of exactly 0,00 causes an import
// error, so zero-amount rows must never be emitted.

export interface LexofficeCsvRow {
  bookingDate: string | Date | null | undefined // Buchungstag
  valueDate?: string | Date | null // Valuta — defaults to bookingDate when omitted
  payerRecipient: string // Auftraggeber/Zahlungsempfänger
  recipientPayer: string // Empfänger/Zahlungspflichtiger
  purpose: string // Vorgang/Verwendungszweck
  amount: number // Betrag (signed EUR)
  extra?: string // Zusatzinfo (optional)
}

export const LEXOFFICE_CSV_HEADER = [
  'Buchungstag',
  'Valuta',
  'Auftraggeber/Zahlungsempfänger',
  'Empfänger/Zahlungspflichtiger',
  'Vorgang/Verwendungszweck',
  'Betrag',
  'Zusatzinfo (optional)'
]

// -> 'DD.MM.YYYY' or ''. Built manually (not toLocaleDateString('de-DE'), which
// omits leading zeros — "24.9.2024" instead of "24.09.2024" — violating
// lexoffice's strict format requirement).
export const formatLexofficeDate = (value: string | Date | null | undefined): string => {
  if (!value) return ''
  const d = value instanceof Date ? value : new Date(value)
  if (isNaN(d.getTime())) return ''
  const dd = String(d.getDate()).padStart(2, '0')
  const mm = String(d.getMonth() + 1).padStart(2, '0')
  const yyyy = d.getFullYear()
  return `${dd}.${mm}.${yyyy}`
}

// -> German comma, 2dp, e.g. '28,20' / '-15,50'.
export const formatLexofficeAmount = (value: number): string => {
  const rounded = Math.round((Number(value) || 0) * 100) / 100
  return rounded.toFixed(2).replace('.', ',')
}

// Strips characters that would break the semicolon-delimited row (the real
// template uses no field quoting, so this — not quoting — is what keeps a row
// well-formed; every field we emit is our own construction, never raw external
// free text, so stripping is sufficient).
export const sanitizeLexofficeField = (value: string): string => {
  return String(value ?? '').replace(/[;\r\n]+/g, ' ').trim()
}

// Header + CRLF-joined rows (matches the real template's own CRLF line endings).
// The single place that enforces lexoffice's "no 0,00 cells" rule: any row whose
// amount rounds to exactly 0 is silently dropped — callers never need to
// duplicate that check themselves.
export const buildLexofficeCsv = (rows: LexofficeCsvRow[]): string => {
  const lines = [LEXOFFICE_CSV_HEADER.join(';')]
  for (const row of rows) {
    const amount = Math.round((Number(row.amount) || 0) * 100) / 100
    if (!amount) continue
    lines.push([
      formatLexofficeDate(row.bookingDate),
      formatLexofficeDate(row.valueDate ?? row.bookingDate),
      sanitizeLexofficeField(row.payerRecipient),
      sanitizeLexofficeField(row.recipientPayer),
      sanitizeLexofficeField(row.purpose),
      formatLexofficeAmount(amount),
      row.extra ? sanitizeLexofficeField(row.extra) : ''
    ].join(';'))
  }
  return lines.join('\r\n')
}

// Builds the CSV and triggers a browser download. UTF-8 with a BOM is used
// rather than matching the template's own ISO-8859-1 byte encoding — lexoffice's
// import wizard lets the user pick the encoding at import time, and UTF-8+BOM is
// simple and robust from browser JS (no manual Latin-1 byte packing needed).
export const downloadLexofficeCsv = (
  rows: LexofficeCsvRow[],
  filename: string
): { rowCount: number; skippedZero: number } => {
  const eligible = rows.filter(r => Math.round((Number(r.amount) || 0) * 100) !== 0)
  const csvContent = buildLexofficeCsv(rows)
  const blob = new Blob(['﻿' + csvContent], { type: 'text/csv;charset=utf-8;' })
  const link = document.createElement('a')
  link.href = URL.createObjectURL(blob)
  link.download = filename
  link.click()
  URL.revokeObjectURL(link.href)
  return { rowCount: eligible.length, skippedZero: rows.length - eligible.length }
}
