/**
 * BKMVDATA record builders — uniform-format-export (wave-13, spec 180).
 *
 * Each builder returns a string beginning with the 4-char record code.
 * Encoding to CP1255 bytes happens at emit time (in generateUniformExport).
 *
 * ITA field conventions:
 * - Numeric fields: zero-padded right-aligned (no decimal separator)
 * - Monetary fields: integer agorot (amount_ILS × 100), no decimal point
 * - Dates: YYYYMMDD
 * - Text fields: left-aligned, space-padded to fixed width, CP1255-safe
 * - The 4-char record code is always chars 1–4 of every line
 */
import type { A000Header, C100Doc, D110Line, D120Payment } from './types'

// ── Field formatters ──────────────────────────────────────────────────────────

/** Right-aligned, zero-padded numeric field */
export function numField(value: number, width: number): string {
  const s = Math.abs(Math.round(value)).toString()
  const padded = s.padStart(width, '0')
  return padded.slice(-width) // truncate if overflow
}

/** Amount in agorot: round(amount * 100) as zero-padded integer */
export function agorot(amountIls: number): number {
  return Math.round(amountIls * 100)
}

/** Date field: YYYYMMDD */
export function dateField(d: string | Date): string {
  if (d instanceof Date) {
    return d.toISOString().slice(0, 10).replace(/-/g, '')
  }
  // Handle ISO date strings (YYYY-MM-DD) or already-formatted YYYYMMDD
  return d.replace(/-/g, '').slice(0, 8)
}

/** Left-aligned text field, space-padded to fixed width, max-truncated */
export function textField(value: string | null | undefined, width: number): string {
  const s = (value ?? '').slice(0, width)
  return s.padEnd(width, ' ')
}

/** Right-aligned text field, space-padded */
export function numTextField(value: string | null | undefined, width: number): string {
  const s = (value ?? '').slice(0, width)
  return s.padStart(width, ' ')
}

// ── Record builders ───────────────────────────────────────────────────────────

/**
 * A000 — Opening / business header
 * Fields (ITA layout):
 *  1-4:   Record code "A000"
 *  5-13:  Software registration number (9 chars)
 *  14-22: Business primary ID / ע.מ / ח.פ (9 chars)
 *  23-30: Period from (YYYYMMDD)
 *  31-38: Period to (YYYYMMDD)
 *  39-78: Business name (40 chars)
 */
export function buildA000(header: A000Header): string {
  return [
    'A000',
    textField(header.softwareRegNo, 9),
    textField(header.businessPrimaryId, 9),
    dateField(header.periodFrom),
    dateField(header.periodTo),
    textField(header.businessName, 40),
  ].join('')
}

/**
 * A100 — Accounting opening record (generated, static)
 * Fields:
 *  1-4:   Record code "A100"
 *  5-8:   Accounting year (YYYY)
 *  9-12:  Accounting period start month (MMDD)
 *  13-16: Accounting period end month (MMDD)
 */
export function buildA100(periodFrom: string, periodTo: string): string {
  const from = periodFrom.replace(/-/g, '').slice(0, 8)
  const to = periodTo.replace(/-/g, '').slice(0, 8)
  const year = from.slice(0, 4)
  const startMMDD = from.slice(4, 8)
  const endMMDD = to.slice(4, 8)
  return `A100${year}${startMMDD}${endMMDD}`
}

/**
 * C100 — Document header (invoice / receipt / credit note)
 * Fields:
 *  1-4:   Record code "C100"
 *  5-9:   Document type code (5 chars)
 *          300 = invoice (חשבונית מס)
 *          305 = credit note (חשבונית זיכוי)
 *          400 = receipt (קבלה)
 *          405 = combined invoice-receipt (חשבונית מס/קבלה)
 *  10-24: Document number (15 chars)
 *  25-32: Issue date (YYYYMMDD)
 *  33-41: Customer ID (9 chars)
 *  42-71: Customer name (30 chars)
 *  72-76: VAT rate * 100 as integer (e.g. 17.00% → 1700, 5 chars)
 *  77-91: Subtotal in agorot (15 chars)
 *  92-106: VAT amount in agorot (15 chars)
 *  107-121: Total in agorot (15 chars)
 *  122-124: Currency code (3 chars)
 */
const DOC_TYPE_CODE: Record<C100Doc['docType'], string> = {
  invoice: '300  ',
  credit_note: '305  ',
  receipt: '400  ',
  invoice_receipt: '405  ',
}

export function buildC100(doc: C100Doc): string {
  return [
    'C100',
    DOC_TYPE_CODE[doc.docType] ?? '300  ',
    textField(doc.docNumber, 15),
    dateField(doc.issueDate),
    textField(doc.customerId ?? '', 9),
    textField(doc.customerName ?? '', 30),
    numField(Math.round((doc.vatRate ?? 0) * 100), 5),
    numField(doc.subtotalAgorot, 15),
    numField(doc.vatAgorot, 15),
    numField(doc.totalAgorot, 15),
    textField(doc.currency || 'ILS', 3),
  ].join('')
}

/**
 * D110 — Document line item
 * Fields:
 *  1-4:   Record code "D110"
 *  5-19:  Document number (15 chars)
 *  20-22: Line position (3 chars, zero-padded)
 *  23-62: Description (40 chars)
 *  63-75: Quantity × 1000 as integer (13 chars) — e.g. 1.5 → 1500
 *  76-90: Unit price in agorot (15 chars)
 *  91-105: Line total in agorot (15 chars)
 *  106:   Taxable flag (1 char: '1' = taxable, '0' = exempt)
 */
export function buildD110(line: D110Line): string {
  return [
    'D110',
    textField(line.docNumber, 15),
    numField(line.linePosition, 3),
    textField(line.description, 40),
    numField(Math.round(line.quantity * 1000), 13),
    numField(line.unitPriceAgorot, 15),
    numField(line.lineTotalAgorot, 15),
    line.taxable ? '1' : '0',
  ].join('')
}

/**
 * D120 — Receipt / payment detail
 * Fields:
 *  1-4:   Record code "D120"
 *  5-19:  Document number (15 chars)
 *  20-22: Line position (3 chars)
 *  23-27: Payment method code (5 chars)
 *          1 = cash, 2 = bank transfer, 3 = cheque, 4 = credit card, 9 = other
 *  28-42: Amount in agorot (15 chars)
 *  43-52: Cheque number (10 chars)
 *  53-57: Bank code (5 chars)
 *  58-62: Branch code (5 chars)
 *  63-72: Account number (10 chars)
 *  73-80: Cheque due date (YYYYMMDD)
 *  81-84: Card last four (4 chars)
 *  85-104: Card brand (20 chars)
 *  105-124: Reference (20 chars)
 */
const PAYMENT_METHOD_CODE: Record<D120Payment['method'], string> = {
  cash: '1    ',
  bank_transfer: '2    ',
  cheque: '3    ',
  credit_card: '4    ',
  other: '9    ',
}

export function buildD120(payment: D120Payment): string {
  return [
    'D120',
    textField(payment.docNumber, 15),
    numField(payment.linePosition, 3),
    PAYMENT_METHOD_CODE[payment.method] ?? '9    ',
    numField(payment.amountAgorot, 15),
    textField(payment.chequeNumber ?? '', 10),
    textField(payment.chequeBank ?? '', 5),
    textField(payment.chequeBranch ?? '', 5),
    textField(payment.chequeAccount ?? '', 10),
    payment.chequeDueDate ? dateField(payment.chequeDueDate) : '        ',
    textField(payment.cardLastFour ?? '', 4),
    textField(payment.cardBrand ?? '', 20),
    textField(payment.reference ?? '', 20),
  ].join('')
}

/**
 * Z900 — Closing record (totals + control sum)
 * Fields:
 *  1-4:   Record code "Z900"
 *  5-19:  C100 record count (15 chars)
 *  20-34: D110 record count (15 chars)
 *  35-49: D120 record count (15 chars)
 *  50-64: B100 record count (15 chars)
 *  65-79: B110 record count (15 chars)
 *  80-94: M100 record count (15 chars)
 *  95-109: Control sum in agorot (15 chars) — sum of all C100 totals
 */
export function buildZ900(counts: Record<string, number>, controlSumIls: number): string {
  return [
    'Z900',
    numField(counts['C100'] ?? 0, 15),
    numField(counts['D110'] ?? 0, 15),
    numField(counts['D120'] ?? 0, 15),
    numField(counts['B100'] ?? 0, 15),
    numField(counts['B110'] ?? 0, 15),
    numField(counts['M100'] ?? 0, 15),
    numField(agorot(controlSumIls), 15),
  ].join('')
}
