// invoice-document.jsx — the print-ready, branded Australian Tax Invoice.
// One renderer for both on-screen preview and Print/Save-PDF (via a hidden iframe).
// Light, fixed colours (like a real paper invoice) so it prints cleanly in any theme.
// Supports multi-line, multi-student (combined siblings) invoices + partial payments.

// AU compliance (GST-registered, sale < $1,000): show the words "Tax invoice",
// seller name + ABN, date of issue, a description of items, and the GST amount.
// We always show buyer identity (parent + student) which also covers the >=$1,000 rule.

function InvoiceDocument({ inv, forPrint = false }) {
  if (!inv) return null;
  const S = INVOICE_SETTINGS;
  const parent = invoiceBillTo(inv);
  const studentIds = inv.studentIds || (inv.studentId ? [inv.studentId] : []);
  const students = studentIds.map(id => SAMPLE_STUDENTS.find(s => s.id === id)).filter(Boolean);
  const family = students.length > 1;
  const reg = S.gstRegistered, gstFree = reg && S.gstFree;
  const title = reg ? 'TAX INVOICE' : 'INVOICE';
  const ov = invoiceOverdueInfo(inv);
  const st = paymentStatus(inv);
  const paid = amountPaid(inv), balance = invoiceBalance(inv), cnT = creditNotesTotal(inv), rfT = refundsTotal(inv), dhT = dishonourFeesTotal(inv);

  const ink = '#1A1815', sub = '#5A574E', faint = '#8A8575', line = '#E8E4D6', brand = '#1F4D3D';
  const nameOf = id => { const s = SAMPLE_STUDENTS.find(x => x.id === id); return s ? `${s.firstName} ${s.lastName}` : ''; };
  const firstNameOf = id => { const s = SAMPLE_STUDENTS.find(x => x.id === id); return s ? s.firstName : ''; };
  const labelStyle = { fontSize: '10px', fontWeight: 700, letterSpacing: '0.07em', textTransform: 'uppercase', color: faint };
  const totalRow = (label, value, opts = {}) => (
    <div style={{ display: 'flex', justifyContent: 'space-between', gap: '16px', padding: '6px 0',
      fontSize: opts.big ? '15px' : '13px', fontWeight: opts.big ? 700 : (opts.bold ? 600 : 400),
      color: opts.muted ? faint : ink, borderTop: opts.rule ? `1px solid ${line}` : 'none' }}>
      <span>{label}</span>
      <span style={{ fontVariantNumeric: 'tabular-nums', color: opts.neg ? '#9A6A2B' : (opts.big ? brand : 'inherit') }}>{value}</span>
    </div>
  );

  // Columns: Description | Start | End | Lessons | Duration | Rate | (spacer) | Amount.
  // A flexible spacer before Amount keeps the line total at the right edge while the
  // Start/End/Lessons/Duration group sits closer to the description on the left.
  const COLS = 'minmax(138px,1fr) 76px 84px 60px 78px 70px minmax(14px,0.4fr) 90px';
  const dayAbbr = d => (DAY_ABBR && DAY_ABBR[d]) || (d ? d.slice(0, 3) : '');
  const lineDesc = l => {
    const cls = l.classId && SAMPLE_CLASSES.find(c => c.id === l.classId);
    let sched = null;
    if (cls) sched = `${dayAbbr(cls.day)} ${cls.startTime}–${cls.endTime}`;
    else if (l.kind === 'private-term' && l.day) sched = `${dayAbbr(l.day)} ${l.startTime}–${l.endTime}`;
    else if (l.kind === 'private' && l.startTime && l.endTime) sched = `${l.startTime}–${l.endTime}`;
    const showBadge = (l.kind === 'class' || l.kind === 'private-term') && l.term;
    return (
      <div>
        <div style={{ display: 'flex', alignItems: 'center', gap: '6px', marginBottom: '4px', flexWrap: 'wrap' }}>
          {family && <span style={{ fontSize: '10px', fontWeight: 700, letterSpacing: '0.04em', textTransform: 'uppercase', color: brand }}>{firstNameOf(l.studentId)}</span>}
          {showBadge && <span style={{ display: 'inline-block', fontSize: '10px', fontWeight: 700, letterSpacing: '0.03em', color: brand, background: 'rgba(31,77,61,0.10)', border: '1px solid rgba(31,77,61,0.25)', borderRadius: '4px', padding: '1px 7px' }}>{l.term}</span>}
        </div>
        <div style={{ fontSize: '13px', fontWeight: 600 }}>{l.description}</div>
        {sched && <div style={{ fontSize: '12px', color: sub, marginTop: '2px' }}>{sched}</div>}
        {l.excludedWeeks && l.excludedWeeks.length > 0 && <div style={{ fontSize: '11px', color: faint, marginTop: '2px' }}>Excl. {l.excludedWeeks.map(w => `Wk ${w}`).join(', ')} — {l.excludedNote || 'no lesson'} (not charged)</div>}
      </div>
    );
  };
  const weekdayOf = d => { try { return new Date(d + 'T00:00:00').toLocaleDateString('en-AU', { weekday: 'short' }); } catch (e) { return ''; } };
  const dash = <span style={{ fontSize: '12px', color: faint }}>—</span>;
  const stackCell = (top, bottom) => (<span style={{ fontSize: '12px', lineHeight: 1.3 }}><span style={{ fontWeight: 600, display: 'block' }}>{top}</span><span style={{ color: faint, fontSize: '11px' }}>{bottom}</span></span>);
  const weekCell = (l, which) => {
    if (l.kind === 'class' || l.kind === 'private-term') return stackCell(`Week ${which === 'start' ? l.firstWeek : l.lastWeek}`, fmtAUDate(which === 'start' ? l.startDate : l.endDate));
    return dash;
  };
  const lessonsCell = l => (l.kind === 'class' || l.kind === 'private-term') ? String(l.qty) : '—';
  const perLessonCell = l => l.hours != null ? `${l.hours}h` : '—';
  const rateCell = l => l.hours != null ? `${fmtAUD(l.rate)}/h` : '—';
  const shortDate = d => { try { return new Date(d + 'T00:00:00').toLocaleDateString('en-AU', { day: 'numeric', month: 'short' }); } catch (e) { return d; } };

  // Main table: term classes + holiday/custom fees (Start/End week columns).
  const renderMainTable = lines => (
    <div style={{ border: `1px solid ${line}`, borderRadius: '10px', overflow: 'hidden' }}>
      <div style={{ display: 'grid', gridTemplateColumns: COLS, gap: '10px', background: '#F3EFE2', padding: '9px 14px', fontSize: '10px', fontWeight: 700, letterSpacing: '0.05em', textTransform: 'uppercase', color: faint }}>
        <span>Description</span><span>Start</span><span>End</span><span style={{ textAlign: 'center' }}>Lessons</span><span style={{ textAlign: 'center' }}>Duration</span><span style={{ textAlign: 'right' }}>Rate</span><span /><span style={{ textAlign: 'right' }}>Amount</span>
      </div>
      {lines.map((l, i) => (
        <div key={l.id || i} style={{ display: 'grid', gridTemplateColumns: COLS, gap: '10px', padding: '12px 14px', alignItems: 'center', background: '#FBFAF6', borderTop: i ? `1px solid ${line}` : 'none' }}>
          {lineDesc(l)}{weekCell(l, 'start')}{weekCell(l, 'end')}
          <span style={{ textAlign: 'center', fontSize: '13px', fontWeight: 600, fontVariantNumeric: 'tabular-nums' }}>{lessonsCell(l)}</span>
          <span style={{ textAlign: 'center', fontSize: '13px', fontVariantNumeric: 'tabular-nums' }}>{perLessonCell(l)}</span>
          <span style={{ textAlign: 'right', fontSize: '13px', fontVariantNumeric: 'tabular-nums' }}>{rateCell(l)}</span><span />
          <span style={{ textAlign: 'right', fontSize: '13px', fontWeight: 600, fontVariantNumeric: 'tabular-nums' }}>{fmtAUD(l.amount != null ? l.amount : lineAmount(l))}</span>
        </div>
      ))}
    </div>
  );

  // Private table: one row per session — each can be a different day, time & duration.
  const renderPrivateTable = lines => {
    const PCOLS = 'minmax(150px,1fr) 104px 122px 64px 66px minmax(14px,0.25fr) 86px';
    const sHours = s => s ? lessonHours({ startTime: s.startTime, endTime: s.endTime }) : 0;
    const rows = [];
    lines.forEach(l => { const sess = l.sessions || []; if (!sess.length) rows.push({ l, s: null, first: true }); else sess.forEach((s, si) => rows.push({ l, s, first: si === 0 })); });
    return (
      <div style={{ border: `1px solid ${line}`, borderRadius: '10px', overflow: 'hidden' }}>
        <div style={{ display: 'grid', gridTemplateColumns: PCOLS, gap: '10px', background: '#F3EFE2', padding: '9px 14px', fontSize: '10px', fontWeight: 700, letterSpacing: '0.05em', textTransform: 'uppercase', color: faint }}>
          <span>Description</span><span>Date</span><span>Time</span><span style={{ textAlign: 'center' }}>Duration</span><span style={{ textAlign: 'right' }}>Rate</span><span /><span style={{ textAlign: 'right' }}>Amount</span>
        </div>
        {rows.map((r, i) => {
          const dur = sHours(r.s);
          return (
            <div key={i} style={{ display: 'grid', gridTemplateColumns: PCOLS, gap: '10px', padding: '10px 14px', alignItems: 'center', background: '#FBFAF6', borderTop: i ? `1px solid ${r.first ? line : '#F1ECDE'}` : 'none' }}>
              <div>{r.first && (<div>{family && <div style={{ fontSize: '10px', fontWeight: 700, letterSpacing: '0.04em', textTransform: 'uppercase', color: brand, marginBottom: '2px' }}>{firstNameOf(r.l.studentId)}</div>}<div style={{ fontSize: '13px', fontWeight: 600 }}>{r.l.description}</div></div>)}</div>
              {r.s ? stackCell(fmtAUDate(r.s.date), weekdayOf(r.s.date)) : dash}
              <span style={{ fontSize: '12px', color: sub }}>{r.s ? `${r.s.startTime}–${r.s.endTime}` : '—'}</span>
              <span style={{ textAlign: 'center', fontSize: '13px', fontVariantNumeric: 'tabular-nums' }}>{r.s ? `${dur}h` : '—'}</span>
              <span style={{ textAlign: 'right', fontSize: '13px', fontVariantNumeric: 'tabular-nums' }}>{fmtAUD(r.l.rate)}/h</span><span />
              <span style={{ textAlign: 'right', fontSize: '13px', fontWeight: 600, fontVariantNumeric: 'tabular-nums' }}>{fmtAUD(Math.round(dur * (r.l.rate || 0) * 100) / 100)}</span>
            </div>
          );
        })}
      </div>
    );
  };

  return (
    <div style={{ background: '#FAF9F5', color: ink, width: forPrint ? '780px' : '100%', margin: forPrint ? '0 auto' : 0,
      fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif',
      border: forPrint ? 'none' : `1px solid ${line}`, borderRadius: forPrint ? 0 : '10px', overflow: 'hidden' }}>

      {/* Letterhead */}
      <div style={{ background: '#FBFAF6', borderBottom: `2px solid ${brand}`, padding: '22px 32px', display: 'flex', alignItems: 'flex-start', justifyContent: 'space-between', gap: '16px' }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: '13px' }}>
          <div style={{ width: 44, height: 44, borderRadius: '10px', background: brand, display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: '16px', fontWeight: 700, color: '#FBFAF6', letterSpacing: '-0.02em', flexShrink: 0 }}>TM</div>
          <div>
            <div style={{ fontSize: '17px', fontWeight: 700, letterSpacing: '-0.01em' }}>{S.businessName}</div>
            <div style={{ fontSize: '11px', color: faint, marginTop: '2px' }}>ABN {S.abn}</div>
            <div style={{ fontSize: '11px', color: faint }}>{S.address}</div>
            <div style={{ fontSize: '11px', color: faint }}>{S.email} · {S.phone}</div>
          </div>
        </div>
        <div style={{ textAlign: 'right' }}>
          <div style={{ fontSize: '20px', fontWeight: 700, letterSpacing: '0.04em', color: brand }}>{title}</div>
          {st === 'paid' && <div style={{ display: 'inline-block', marginTop: '8px', border: '2.5px solid #4A9B7E', color: '#3E8E6C', fontSize: '18px', fontWeight: 800, letterSpacing: '0.16em', padding: '2px 10px', borderRadius: '6px' }}>PAID</div>}
          {st === 'partial' && <div style={{ marginTop: '8px', fontSize: '11px', fontWeight: 700, color: '#B8922A' }}>PART-PAID · {fmtAUD(balance)} due</div>}
          {st === 'written-off' && <div style={{ display: 'inline-block', marginTop: '8px', border: '2px solid #9A96A6', color: '#7A7367', fontSize: '16px', fontWeight: 800, letterSpacing: '0.12em', padding: '2px 10px', borderRadius: '6px' }}>WRITTEN OFF</div>}
          {st === 'credited' && <div style={{ display: 'inline-block', marginTop: '8px', border: '2px solid #5B8FCF', color: '#4A7C9B', fontSize: '16px', fontWeight: 800, letterSpacing: '0.1em', padding: '2px 10px', borderRadius: '6px' }}>CREDITED</div>}
          {st === 'refunded' && <div style={{ display: 'inline-block', marginTop: '8px', border: '2px solid #9B6AC0', color: '#7A5C8B', fontSize: '15px', fontWeight: 800, letterSpacing: '0.1em', padding: '2px 10px', borderRadius: '6px' }}>REFUNDED</div>}
          {ov.overdue && <div style={{ marginTop: '6px', fontSize: '11px', fontWeight: 700, color: ov.flag ? '#C05656' : '#B8922A' }}>{ov.flag ? '⚑ ' : ''}{ov.daysOverdue} day{ov.daysOverdue === 1 ? '' : 's'} overdue</div>}
        </div>
      </div>

      <div style={{ padding: forPrint ? '24px 32px' : '24px 28px' }}>
        {/* Bill-to + meta */}
        <div style={{ display: 'flex', justifyContent: 'space-between', gap: '24px', flexWrap: 'wrap', alignItems: 'flex-start', marginBottom: '22px' }}>
          <div style={{ minWidth: '220px' }}>
            <div style={labelStyle}>Bill to</div>
            <div style={{ fontSize: '14px', fontWeight: 600, marginTop: '5px' }}>{parent ? `${parent.firstName} ${parent.lastName}` : '—'}</div>
            {parent && <div style={{ fontSize: '12px', color: sub }}>{parent.email}</div>}
            {parent && <div style={{ fontSize: '12px', color: sub }}>{parent.mobile}</div>}
            <div style={{ marginTop: '10px', fontSize: '12px', color: sub }}>
              <span style={{ color: faint }}>{family ? 'Students: ' : 'Student: '}</span>
              {students.map((s, i) => (<span key={s.id}><strong style={{ fontWeight: 600, color: ink }}>{s.firstName} {s.lastName}</strong><span style={{ color: faint }}> ({customerNo(s)})</span>{i < students.length - 1 ? ', ' : ''}</span>))}
            </div>
          </div>
          {/* Payment summary — invoice number (payment reference) + due date, emphasised */}
          <div style={{ minWidth: '240px', maxWidth: '300px', border: '1px solid rgba(31,77,61,0.28)', background: 'rgba(31,77,61,0.05)', borderRadius: '10px', padding: '12px 14px' }}>
            <div style={{ fontSize: '9.5px', fontWeight: 700, letterSpacing: '0.07em', textTransform: 'uppercase', color: faint }}>Invoice number</div>
            <div style={{ fontSize: '17px', fontWeight: 700, color: brand, fontFamily: 'ui-monospace, SFMono-Regular, Menlo, monospace', marginTop: '2px' }}>{inv.number}</div>
            <div style={{ fontSize: '10.5px', color: faint, marginTop: '2px' }}>Quote this as your payment reference</div>
            <div style={{ height: 1, background: 'rgba(31,77,61,0.18)', margin: '10px 0' }} />
            <div style={{ display: 'flex', justifyContent: 'space-between', gap: '12px' }}>
              <div>
                <div style={{ fontSize: '9.5px', fontWeight: 700, letterSpacing: '0.07em', textTransform: 'uppercase', color: faint }}>Due date</div>
                <div style={{ fontSize: '15px', fontWeight: 700, marginTop: '2px', color: st === 'paid' ? faint : (ov.overdue ? '#C05656' : ink) }}>{fmtAUDate(inv.dueDate)}</div>
              </div>
              <div style={{ textAlign: 'right' }}>
                <div style={{ fontSize: '9.5px', fontWeight: 700, letterSpacing: '0.07em', textTransform: 'uppercase', color: faint }}>{st === 'partial' ? 'Balance due' : 'Amount due'}</div>
                <div style={{ fontSize: '15px', fontWeight: 700, marginTop: '2px', fontVariantNumeric: 'tabular-nums', color: st === 'paid' ? '#3E8E6C' : brand }}>{fmtAUD(st === 'paid' ? 0 : (balance > 0 ? balance : inv.totalInc))}</div>
              </div>
            </div>
            <div style={{ fontSize: '10.5px', color: faint, marginTop: '10px' }}>Issued {fmtAUDate(inv.issueDate)} · {students[0] ? students[0].campus : '—'}</div>
          </div>
        </div>

        {/* Line items — split into term tuition vs private lessons */}
        {(() => {
          const mainLines = (inv.lines || []).filter(l => l.kind !== 'private');
          const privLines = (inv.lines || []).filter(l => l.kind === 'private');
          const both = mainLines.length > 0 && privLines.length > 0;
          const grpLabel = txt => <div style={{ fontSize: '10px', fontWeight: 700, letterSpacing: '0.06em', textTransform: 'uppercase', color: faint, margin: '0 0 8px' }}>{txt}</div>;
          return (
            <div style={{ display: 'flex', flexDirection: 'column', gap: '16px' }}>
              {mainLines.length > 0 && <div>{both && grpLabel('Term tuition & fees')}{renderMainTable(mainLines)}</div>}
              {privLines.length > 0 && <div>{both && grpLabel('Private lessons')}{renderPrivateTable(privLines)}</div>}
            </div>
          );
        })()}

        {/* Totals */}
        <div style={{ display: 'flex', justifyContent: 'flex-end', marginTop: '14px' }}>
          <div style={{ width: '340px', maxWidth: '100%' }}>
            {totalRow('Subtotal', fmtAUD(inv.subtotal != null ? inv.subtotal : inv.lineInc))}
            {(inv.discountsApplied || []).map((d, i) => (
              <div key={i}>{totalRow(`${family && d.studentId ? firstNameOf(d.studentId) + ' · ' : ''}${d.name}${d.kind === 'percent' ? ` (${d.value}%)` : ''}`, `−${fmtAUD(d.amount)}`, { neg: true })}</div>
            ))}
            {(inv.creditLines || []).map((c, i) => (
              <div key={i}>{totalRow(`${family ? firstNameOf(c.studentId) + ' · ' : ''}Credit applied`, `−${fmtAUD(c.amount)}`, { neg: true })}</div>
            ))}
            {!inv.creditLines && inv.creditApplied > 0 && totalRow('Credit applied', `−${fmtAUD(inv.creditApplied)}`, { neg: true })}
            {reg && totalRow(gstFree ? 'GST (GST-free supply)' : 'Includes GST (10%)', fmtAUD(inv.gst), { muted: true })}
            {totalRow(reg ? 'Total (incl. GST)' : 'Total due', fmtAUD(inv.totalInc), { big: true, rule: true })}
            {(inv.creditNotes || []).map((c, i) => <div key={'cn' + i}>{totalRow(`Credit note ${c.number}`, `−${fmtAUD(c.amount)}`, { neg: true })}</div>)}
            {dhT > 0 && totalRow('Dishonour fees', fmtAUD(dhT))}
            {paid > 0 && totalRow('Amount paid', `−${fmtAUD(paid)}`, { neg: true })}
            {rfT > 0 && totalRow('Refund issued', fmtAUD(rfT))}
            {(paid > 0 || cnT > 0 || rfT > 0 || dhT > 0) && totalRow('Balance due', fmtAUD(balance), { bold: true, rule: true })}
            {/* Cash alternative (only while still owing) */}
            {(st === 'unpaid' || st === 'partial') && (
              <div style={{ marginTop: '10px', background: 'rgba(31,77,61,0.06)', border: `1px solid rgba(31,77,61,0.18)`, borderRadius: '8px', padding: '8px 12px', display: 'flex', justifyContent: 'space-between', alignItems: 'center' }}>
                <span style={{ fontSize: '12px', color: brand, fontWeight: 600 }}>Pay by cash &amp; save {S.cashDiscountPct}%</span>
                <span style={{ fontSize: '14px', fontWeight: 700, color: brand, fontVariantNumeric: 'tabular-nums' }}>{fmtAUD(inv.cashPrice)}</span>
              </div>
            )}
          </div>
        </div>

        {/* Payment plan schedule (direct debit) */}
        {inv.plan && (
          <div style={{ marginTop: '20px', border: '1px solid rgba(31,77,61,0.25)', background: 'rgba(31,77,61,0.04)', borderRadius: '10px', overflow: 'hidden' }}>
            <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', padding: '10px 14px', background: 'rgba(31,77,61,0.08)' }}>
              <span style={{ fontSize: '11px', fontWeight: 700, letterSpacing: '0.05em', textTransform: 'uppercase', color: brand }}>Payment plan · {inv.plan.cadence} · direct debit</span>
              <span style={{ fontSize: '11px', color: sub }}>{inv.plan.instalments.length} instalments</span>
            </div>
            {inv.plan.instalments.map((ins, i) => (
              <div key={ins.id} style={{ display: 'grid', gridTemplateColumns: '22px 1fr 100px 84px', gap: '10px', alignItems: 'center', padding: '8px 14px', borderTop: i ? `1px solid ${line}` : 'none', fontSize: '12px' }}>
                <span style={{ color: faint }}>{i + 1}</span>
                <span style={{ color: ink }}>{fmtAUDate(ins.date)}</span>
                <span style={{ textAlign: 'right', fontVariantNumeric: 'tabular-nums', fontWeight: 600 }}>{fmtAUD(ins.amount)}</span>
                <span style={{ textAlign: 'right', fontSize: '11px', fontWeight: 600, color: ins.status === 'paid' ? '#3E8E6C' : ins.status === 'failed' ? '#C05656' : faint }}>{ins.status === 'paid' ? 'Paid' : ins.status === 'failed' ? 'Failed' : 'Scheduled'}</span>
              </div>
            ))}
            <div style={{ padding: '8px 14px', borderTop: `1px solid ${line}`, fontSize: '10.5px', color: faint }}>Auto-debited from your nominated bank account. A failed payment incurs a {fmtAUD(S.dishonourFee)} dishonour fee.</div>
          </div>
        )}

        {/* How to pay (while a balance is owing) */}
        {(st === 'unpaid' || st === 'partial') && (
          <div style={{ marginTop: '24px', borderTop: `1px solid ${line}`, paddingTop: '18px' }}>
            <div style={labelStyle}>How to pay</div>
            {forPrint
              ? <div style={{ marginTop: '10px', fontSize: '12px', color: ink }}>Pay securely online by card or direct debit: <span style={{ color: brand, wordBreak: 'break-all' }}>{S.stripeBaseUrl}</span></div>
              : <a href={S.stripeBaseUrl} target="_blank" rel="noopener noreferrer" style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginTop: '10px', background: brand, color: '#FBFAF6', padding: '12px 18px', borderRadius: '8px', textDecoration: 'none', fontWeight: 700, fontSize: '14px' }}><span>💳 Pay now — card or direct debit</span><span style={{ fontVariantNumeric: 'tabular-nums' }}>{fmtAUD(balance)} →</span></a>}
            <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '12px', marginTop: '12px' }}>
              {!inv.plan && (
                <div style={{ border: `1px solid ${line}`, borderRadius: '8px', padding: '12px', background: '#FBFAF6' }}>
                  <div style={{ fontSize: '12px', fontWeight: 700, marginBottom: '4px' }}>📆 Pay by instalments</div>
                  <div style={{ fontSize: '11px', color: sub, lineHeight: 1.5 }}>Spread it over weekly, fortnightly or monthly direct debits (finishing before term ends) — just ask us to set up a plan.</div>
                </div>
              )}
              <div style={{ border: `1px solid ${line}`, borderRadius: '8px', padding: '12px', background: '#FBFAF6' }}>
                <div style={{ fontSize: '12px', fontWeight: 700, marginBottom: '4px' }}>💵 Cash</div>
                <div style={{ fontSize: '11px', color: sub, lineHeight: 1.5 }}>Pay in person and save {S.cashDiscountPct}%: <strong style={{ color: brand }}>{fmtAUD(inv.cashPrice)}</strong>.</div>
              </div>
            </div>
          </div>
        )}

        {inv.notes && <div style={{ marginTop: '18px', fontSize: '12px', color: sub }}><span style={{ color: faint, fontWeight: 600 }}>Notes: </span>{inv.notes}</div>}

        <div style={{ marginTop: '22px', paddingTop: '14px', borderTop: `1px solid ${line}`, textAlign: 'center', fontSize: '11px', color: faint }}>
          {(st === 'paid' || st === 'credited') ? 'This invoice is settled — thank you! This document also serves as your receipt.' : `Thank you for studying with ${S.businessName}. Payment is due within ${S.paymentTermsDays} days of issue.`}
          {reg && (gstFree ? ' Tuition is a GST-free supply.' : ' Total price includes GST.')}
        </div>
      </div>
    </div>
  );
}

// Print / Save-PDF — render the same component into a hidden iframe and print it.
function printInvoiceDocument(inv) {
  const frame = document.createElement('iframe');
  frame.style.cssText = 'position:fixed;right:0;bottom:0;width:0;height:0;border:0;';
  document.body.appendChild(frame);
  const doc = frame.contentDocument || frame.contentWindow.document;
  doc.open();
  doc.write(`<!doctype html><html><head><meta charset="utf-8"><title>${inv.number}</title>
    <style>@page{margin:14mm;} body{margin:0;background:#fff;-webkit-print-color-adjust:exact;print-color-adjust:exact;}</style>
    </head><body><div id="inv"></div></body></html>`);
  doc.close();
  const root = ReactDOM.createRoot(doc.getElementById('inv'));
  root.render(<InvoiceDocument inv={inv} forPrint />);
  setTimeout(() => {
    try { frame.contentWindow.focus(); frame.contentWindow.print(); } catch (e) {}
    setTimeout(() => { try { root.unmount(); } catch (e) {} document.body.removeChild(frame); }, 1500);
  }, 450);
}

// ── Adjustment note (credit note) document — same branded language ────────────
function CreditNoteDocument({ note, inv, forPrint = false }) {
  if (!note || !inv) return null;
  const S = INVOICE_SETTINGS;
  const parent = SAMPLE_PARENTS.find(p => p.id === inv.billToParentId);
  const students = (inv.studentIds || []).map(id => SAMPLE_STUDENTS.find(s => s.id === id)).filter(Boolean);
  const reg = S.gstRegistered, gstFree = reg && S.gstFree;
  const gst = (reg && !gstFree) ? Math.round((note.amount / 11) * 100) / 100 : 0;
  const ink = '#1A1815', sub = '#5A574E', faint = '#8A8575', line = '#E8E4D6', brand = '#1F4D3D';
  const lbl = { fontSize: '10px', fontWeight: 700, letterSpacing: '0.07em', textTransform: 'uppercase', color: faint };
  const row = (label, value, opts = {}) => (
    <div style={{ display: 'flex', justifyContent: 'space-between', gap: '16px', padding: '6px 0', fontSize: opts.big ? '15px' : '13px', fontWeight: opts.big ? 700 : (opts.bold ? 600 : 400), color: opts.muted ? faint : ink, borderTop: opts.rule ? `1px solid ${line}` : 'none' }}>
      <span>{label}</span><span style={{ fontVariantNumeric: 'tabular-nums', color: opts.big ? brand : 'inherit' }}>{value}</span>
    </div>
  );
  return (
    <div style={{ background: '#FAF9F5', color: ink, width: forPrint ? '780px' : '100%', margin: forPrint ? '0 auto' : 0, fontFamily: '-apple-system, BlinkMacSystemFont, "Segoe UI", system-ui, sans-serif', border: forPrint ? 'none' : `1px solid ${line}`, borderRadius: forPrint ? 0 : '10px', overflow: 'hidden' }}>
      <div style={{ background: '#FBFAF6', borderBottom: `2px solid ${brand}`, padding: '22px 32px', display: 'flex', alignItems: 'flex-start', justifyContent: 'space-between', gap: '16px' }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: '13px' }}>
          <div style={{ width: 44, height: 44, borderRadius: '10px', background: brand, display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: '16px', fontWeight: 700, color: '#FBFAF6', flexShrink: 0 }}>TM</div>
          <div>
            <div style={{ fontSize: '17px', fontWeight: 700 }}>{S.businessName}</div>
            <div style={{ fontSize: '11px', color: faint, marginTop: '2px' }}>ABN {S.abn}</div>
            <div style={{ fontSize: '11px', color: faint }}>{S.address}</div>
            <div style={{ fontSize: '11px', color: faint }}>{S.email} · {S.phone}</div>
          </div>
        </div>
        <div style={{ textAlign: 'right' }}><div style={{ fontSize: '20px', fontWeight: 700, letterSpacing: '0.03em', color: brand }}>ADJUSTMENT NOTE</div></div>
      </div>
      <div style={{ padding: '24px 32px' }}>
        <div style={{ display: 'flex', justifyContent: 'space-between', gap: '24px', flexWrap: 'wrap', alignItems: 'flex-start', marginBottom: '22px' }}>
          <div style={{ minWidth: '220px' }}>
            <div style={lbl}>Issued to</div>
            <div style={{ fontSize: '14px', fontWeight: 600, marginTop: '5px' }}>{parent ? `${parent.firstName} ${parent.lastName}` : '—'}</div>
            {parent && <div style={{ fontSize: '12px', color: sub }}>{parent.email}</div>}
            <div style={{ marginTop: '10px', fontSize: '12px', color: sub }}><span style={{ color: faint }}>{students.length > 1 ? 'Students: ' : 'Student: '}</span>{students.map((s, i) => (<span key={s.id}><strong style={{ color: ink, fontWeight: 600 }}>{s.firstName} {s.lastName}</strong>{i < students.length - 1 ? ', ' : ''}</span>))}</div>
          </div>
          <div style={{ minWidth: '240px', maxWidth: '300px', border: '1px solid rgba(31,77,61,0.28)', background: 'rgba(31,77,61,0.05)', borderRadius: '10px', padding: '12px 14px' }}>
            <div style={lbl}>Adjustment note</div>
            <div style={{ fontSize: '17px', fontWeight: 700, color: brand, fontFamily: 'ui-monospace, monospace', marginTop: '2px' }}>{note.number}</div>
            <div style={{ height: 1, background: 'rgba(31,77,61,0.18)', margin: '10px 0' }} />
            <div style={{ display: 'flex', justifyContent: 'space-between', fontSize: '12px' }}><span style={{ color: faint }}>Date</span><strong style={{ color: ink }}>{fmtAUDate(note.date)}</strong></div>
            <div style={{ display: 'flex', justifyContent: 'space-between', fontSize: '12px', marginTop: '4px' }}><span style={{ color: faint }}>Against invoice</span><strong style={{ color: ink }}>{inv.number}</strong></div>
          </div>
        </div>
        <div style={{ border: `1px solid ${line}`, borderRadius: '10px', overflow: 'hidden' }}>
          <div style={{ display: 'grid', gridTemplateColumns: '1fr 110px', gap: '10px', background: '#F3EFE2', padding: '9px 14px', fontSize: '10px', fontWeight: 700, letterSpacing: '0.05em', textTransform: 'uppercase', color: faint }}><span>Description</span><span style={{ textAlign: 'right' }}>Amount</span></div>
          <div style={{ display: 'grid', gridTemplateColumns: '1fr 110px', gap: '10px', padding: '12px 14px', alignItems: 'center', background: '#FBFAF6' }}>
            <div><div style={{ fontSize: '13px', fontWeight: 600 }}>Adjustment — {note.reason || 'credit'}</div><div style={{ fontSize: '11px', color: faint, marginTop: '2px' }}>Credit against {inv.number}</div></div>
            <span style={{ textAlign: 'right', fontSize: '13px', fontWeight: 600, fontVariantNumeric: 'tabular-nums' }}>{fmtAUD(note.amount)}</span>
          </div>
        </div>
        <div style={{ display: 'flex', justifyContent: 'flex-end', marginTop: '14px' }}>
          <div style={{ width: '320px', maxWidth: '100%' }}>
            {row('Subtotal', fmtAUD(note.amount))}
            {reg && row(gstFree ? 'GST (GST-free)' : 'Includes GST (10%)', fmtAUD(gst), { muted: true })}
            {row('Total credit', fmtAUD(note.amount), { big: true, rule: true })}
          </div>
        </div>
        <div style={{ marginTop: '18px', fontSize: '12px', color: sub }}><span style={{ color: faint, fontWeight: 600 }}>Applied to: </span>{inv.number} — reduces that invoice's balance.</div>
        <div style={{ marginTop: '22px', paddingTop: '14px', borderTop: `1px solid ${line}`, textAlign: 'center', fontSize: '11px', color: faint }}>Adjustment note for {S.businessName}.{reg ? ' Total includes GST.' : ''}</div>
      </div>
    </div>
  );
}
function printCreditNote(note, inv) {
  const frame = document.createElement('iframe'); frame.style.cssText = 'position:fixed;right:0;bottom:0;width:0;height:0;border:0;'; document.body.appendChild(frame);
  const doc = frame.contentDocument || frame.contentWindow.document; doc.open();
  doc.write(`<!doctype html><html><head><meta charset="utf-8"><title>${note.number}</title><style>@page{margin:14mm;}body{margin:0;background:#fff;-webkit-print-color-adjust:exact;print-color-adjust:exact;}</style></head><body><div id="cn"></div></body></html>`); doc.close();
  const root = ReactDOM.createRoot(doc.getElementById('cn')); root.render(<CreditNoteDocument note={note} inv={inv} forPrint />);
  setTimeout(() => { try { frame.contentWindow.focus(); frame.contentWindow.print(); } catch (e) {} setTimeout(() => { try { root.unmount(); } catch (e) {} document.body.removeChild(frame); }, 1500); }, 450);
}

Object.assign(window, { InvoiceDocument, printInvoiceDocument, CreditNoteDocument, printCreditNote });
