// MaxAMove — Job Photos, Auto-Invoice, Shareable Portal Links

// ─── TOAST SYSTEM ─────────────────────────────────────────────
function showToast(msg, type = 'success') {
  const id = 'toast-' + Date.now();
  const el = document.createElement('div');
  el.id = id;
  const color = type === 'success' ? '#16a34a' : type === 'error' ? '#ef4444' : '#14C6BF';
  const bg = type === 'success' ? '#f0fdf4' : type === 'error' ? '#fef2f2' : '#f0fdfb';
  el.style.cssText = `position:fixed;bottom:24px;left:50%;transform:translateX(-50%) translateY(100px);background:${bg};border:1.5px solid ${color};color:${color};padding:14px 22px;border-radius:12px;font-weight:700;font-family:'DM Sans',sans-serif;font-size:14px;z-index:9999;box-shadow:0 12px 40px rgba(0,0,0,0.12);opacity:0;transition:all .3s cubic-bezier(.4,0,.2,1);max-width:90%;text-align:center;line-height:1.4;pointer-events:none;`;
  el.innerHTML = msg;
  document.body.appendChild(el);
  requestAnimationFrame(() => {
    el.style.opacity = '1';
    el.style.transform = 'translateX(-50%) translateY(0)';
  });
  setTimeout(() => {
    el.style.opacity = '0';
    el.style.transform = 'translateX(-50%) translateY(20px)';
    setTimeout(() => el.remove(), 350);
  }, 3400);
}

// ─── INVOICE AUTO-GEN FROM JOB ────────────────────────────────
function createInvoiceFromJob(job) {
  let invoices = [];
  try { invoices = JSON.parse(localStorage.getItem('crm_invoices')) || []; } catch {}
  // Skip if already created
  if (invoices.find(i => i.jobId === job.id)) return invoices.find(i => i.jobId === job.id);
  const invNum = 'INV-' + new Date().getFullYear() + '-' + String(invoices.length + 101).padStart(3, '0');
  const inv = {
    id: invNum,
    jobId: job.id,
    customer: job.customer,
    phone: job.phone,
    issued: new Date().toISOString().split('T')[0],
    due: (() => { const d = new Date(); d.setDate(d.getDate() + 7); return d.toISOString().split('T')[0]; })(),
    moveDate: job.date,
    from: job.from,
    to: job.to,
    lineItems: [
      { desc: `Moving Services — ${job.from} → ${job.to}`, qty: 1, rate: job.value, amount: job.value },
    ],
    subtotal: job.value,
    tax: 0,
    total: job.value,
    status: 'unpaid', // unpaid | paid | overdue
    paid: 0,
    createdFromJob: true,
  };
  invoices.unshift(inv);
  localStorage.setItem('crm_invoices', JSON.stringify(invoices));
  return inv;
}

function getInvoices() {
  try { return JSON.parse(localStorage.getItem('crm_invoices')) || []; } catch { return []; }
}
function saveInvoices(list) { localStorage.setItem('crm_invoices', JSON.stringify(list)); }

// ─── PHOTO STORAGE ────────────────────────────────────────────
function getJobPhotos(jobId) {
  try { return (JSON.parse(localStorage.getItem('crm_job_photos')) || {})[jobId] || []; } catch { return []; }
}
function saveJobPhotos(jobId, photos) {
  let all = {};
  try { all = JSON.parse(localStorage.getItem('crm_job_photos')) || {}; } catch {}
  all[jobId] = photos;
  try { localStorage.setItem('crm_job_photos', JSON.stringify(all)); }
  catch (e) { showToast('Storage full — try fewer or smaller photos', 'error'); }
}

// Resize + compress image file to JPEG data URL, max 1200px
function resizeImageFile(file, maxDim = 1200, quality = 0.82) {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.onload = (e) => {
      const img = new Image();
      img.onload = () => {
        let { width, height } = img;
        if (width > maxDim || height > maxDim) {
          const scale = Math.min(maxDim / width, maxDim / height);
          width = Math.round(width * scale);
          height = Math.round(height * scale);
        }
        const canvas = document.createElement('canvas');
        canvas.width = width;
        canvas.height = height;
        const ctx = canvas.getContext('2d');
        ctx.drawImage(img, 0, 0, width, height);
        resolve(canvas.toDataURL('image/jpeg', quality));
      };
      img.onerror = reject;
      img.src = e.target.result;
    };
    reader.onerror = reject;
    reader.readAsDataURL(file);
  });
}

// ─── SHAREABLE PORTAL LINK ────────────────────────────────────
// Encode BOL/invoice to URL hash so a customer on a phone can view + sign.
// Two modes:
//   1. localStorage token (short URL, same-device only) — used when data is too big for URL
//   2. Self-contained base64 payload in URL — works on ANY device, URL is long
// We try self-contained first (so real phone testing works), fall back to token.
function createPortalLink(kind, data) {
  const base = window.location.href.replace(/\/[^/]*$/, '/');
  // Strip photos from BOLs for URL-encoding (too heavy); portal doesn't need them for signing.
  const slim = { ...data };
  // Try self-contained first
  try {
    const payload = { kind, data: slim, created: Date.now() };
    const json = JSON.stringify(payload);
    // Base64url encode (safe in URLs)
    const b64 = btoa(unescape(encodeURIComponent(json)))
      .replace(/\+/g, '-').replace(/\//g, '_').replace(/=+$/, '');
    // If the URL is reasonable (< 6KB), use self-contained
    if (b64.length < 6000) {
      // Also register a localStorage token so the CRM can receive sig sync when signed on same device
      const token = 'p' + Date.now().toString(36) + Math.random().toString(36).slice(2, 6);
      let shares = {};
      try { shares = JSON.parse(localStorage.getItem('crm_portal_shares')) || {}; } catch {}
      shares[token] = { kind, data: slim, created: Date.now() };
      localStorage.setItem('crm_portal_shares', JSON.stringify(shares));
      // Include BOTH the token and the inline payload — portal prefers token if found locally
      return base + 'portal.html#t=' + token + '&d=' + b64;
    }
  } catch (e) {}
  // Fallback: token-only (same device only)
  const token = 'p' + Date.now().toString(36) + Math.random().toString(36).slice(2, 6);
  let shares = {};
  try { shares = JSON.parse(localStorage.getItem('crm_portal_shares')) || {}; } catch {}
  shares[token] = { kind, data: slim, created: Date.now() };
  localStorage.setItem('crm_portal_shares', JSON.stringify(shares));
  return base + 'portal.html#' + token;
}

// ─── JOB PHOTO GRID COMPONENT (reusable) ──────────────────────
function JobPhotoGrid({ jobId, label = 'Job Photos', compact = false }) {
  const [photos, setPhotos] = React.useState(() => getJobPhotos(jobId));
  const [uploading, setUploading] = React.useState(false);
  const [viewing, setViewing] = React.useState(null);
  const fileRef = React.useRef(null);

  React.useEffect(() => { saveJobPhotos(jobId, photos); }, [photos, jobId]);

  const handleFiles = async (files) => {
    if (!files || !files.length) return;
    setUploading(true);
    const added = [];
    for (const file of files) {
      if (!file.type.startsWith('image/')) continue;
      try {
        const dataUrl = await resizeImageFile(file);
        added.push({
          id: Date.now() + '-' + Math.random().toString(36).slice(2, 7),
          name: file.name,
          size: file.size,
          uploaded: new Date().toISOString(),
          caption: '',
          tag: 'before', // before | after | damage | receipt
          dataUrl,
        });
      } catch (e) { /* skip failed */ }
    }
    setPhotos(prev => [...added, ...prev]);
    setUploading(false);
    if (added.length) showToast(`${added.length} photo${added.length > 1 ? 's' : ''} uploaded`);
  };

  const removePhoto = (id) => {
    if (!confirm('Delete this photo?')) return;
    setPhotos(prev => prev.filter(p => p.id !== id));
    setViewing(null);
  };

  const updatePhoto = (id, updates) => {
    setPhotos(prev => prev.map(p => p.id === id ? { ...p, ...updates } : p));
  };

  const TAG_COLORS = {
    before: { bg: '#e0f2fe', color: '#0369a1' },
    after: { bg: '#f0fdf4', color: '#16a34a' },
    damage: { bg: '#fef2f2', color: '#dc2626' },
    receipt: { bg: '#fef3c7', color: '#b45309' },
  };

  return (
    <div>
      {!compact && (
        <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 12 }}>
          <div>
            <div style={{ fontWeight: 800, fontSize: 14, fontFamily: 'Poppins' }}>{label}</div>
            <div style={{ fontSize: 11, color: 'var(--muted)' }}>{photos.length} photo{photos.length !== 1 ? 's' : ''} · documenting condition, damage & receipts</div>
          </div>
          <button onClick={() => fileRef.current?.click()} disabled={uploading}
            style={{ padding: '8px 14px', borderRadius: 9, border: 'none', background: 'var(--accent)', color: '#fff', cursor: uploading ? 'wait' : 'pointer', fontWeight: 700, fontFamily: 'inherit', fontSize: 13, opacity: uploading ? 0.6 : 1, display: 'inline-flex', alignItems: 'center', gap: 6 }}>
            {uploading ? 'Processing…' : <><Icon name="plus" size={13} color="#fff"/> Add Photos</>}
          </button>
        </div>
      )}

      <input ref={fileRef} type="file" accept="image/*" multiple capture="environment"
        style={{ display: 'none' }} onChange={e => { handleFiles(e.target.files); e.target.value = ''; }} />

      {photos.length === 0 ? (
        <div onClick={() => fileRef.current?.click()}
          style={{ border: '2px dashed var(--border)', borderRadius: 12, padding: compact ? '24px 16px' : '40px 20px', textAlign: 'center', cursor: 'pointer', background: 'var(--bg)' }}>
          <div style={{ marginBottom: 8, display: 'flex', justifyContent: 'center' }}><Icon name="eye" size={compact ? 28 : 38} color="var(--muted)"/></div>
          <div style={{ fontWeight: 700, fontSize: 14, marginBottom: 4 }}>Tap to add photos</div>
          <div style={{ fontSize: 12, color: 'var(--muted)' }}>On mobile: opens your camera · On desktop: pick from files</div>
        </div>
      ) : (
        <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill,minmax(140px,1fr))', gap: 10 }}>
          {photos.map(p => {
            const tag = TAG_COLORS[p.tag] || TAG_COLORS.before;
            return (
              <div key={p.id} onClick={() => setViewing(p)}
                style={{ position: 'relative', aspectRatio: '1', borderRadius: 10, overflow: 'hidden', cursor: 'pointer', background: '#000', border: '1px solid var(--border)' }}>
                <img src={p.dataUrl} style={{ width: '100%', height: '100%', objectFit: 'cover' }} alt={p.caption || p.name} />
                <div style={{ position: 'absolute', top: 6, left: 6, background: tag.bg, color: tag.color, padding: '2px 8px', borderRadius: 10, fontSize: 10, fontWeight: 800, textTransform: 'uppercase', letterSpacing: '.06em' }}>{p.tag}</div>
                {p.caption && (
                  <div style={{ position: 'absolute', bottom: 0, left: 0, right: 0, background: 'linear-gradient(transparent,rgba(0,0,0,.75))', color: '#fff', padding: '14px 8px 6px', fontSize: 11, fontWeight: 600 }}>{p.caption}</div>
                )}
              </div>
            );
          })}
          {/* Add tile */}
          <div onClick={() => fileRef.current?.click()}
            style={{ aspectRatio: '1', borderRadius: 10, border: '2px dashed var(--border)', display: 'flex', alignItems: 'center', justifyContent: 'center', cursor: 'pointer', flexDirection: 'column', gap: 4, color: 'var(--muted)', background: 'var(--bg)' }}>
            <div style={{ fontSize: 24 }}>＋</div>
            <div style={{ fontSize: 11, fontWeight: 700 }}>Add</div>
          </div>
        </div>
      )}

      {/* Lightbox */}
      {viewing && (
        <div onClick={() => setViewing(null)}
          style={{ position: 'fixed', inset: 0, background: 'rgba(0,0,0,.92)', zIndex: 10000, display: 'flex', flexDirection: 'column', padding: 20 }}>
          <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 14 }} onClick={e => e.stopPropagation()}>
            <div style={{ color: '#fff', fontWeight: 700 }}>{viewing.name}</div>
            <div style={{ display: 'flex', gap: 8 }}>
              <button onClick={() => removePhoto(viewing.id)} style={{ padding: '6px 12px', borderRadius: 7, border: 'none', background: '#dc2626', color: '#fff', cursor: 'pointer', fontWeight: 700, fontSize: 12 }}>Delete</button>
              <button onClick={() => setViewing(null)} style={{ padding: '6px 14px', borderRadius: 7, border: 'none', background: 'rgba(255,255,255,.15)', color: '#fff', cursor: 'pointer', fontWeight: 700, fontSize: 12 }}>Close ×</button>
            </div>
          </div>
          <div style={{ flex: 1, display: 'flex', alignItems: 'center', justifyContent: 'center', overflow: 'hidden' }} onClick={e => e.stopPropagation()}>
            <img src={viewing.dataUrl} style={{ maxWidth: '100%', maxHeight: '100%', objectFit: 'contain', borderRadius: 8 }} />
          </div>
          <div onClick={e => e.stopPropagation()} style={{ marginTop: 14, display: 'flex', gap: 10, flexWrap: 'wrap', alignItems: 'center' }}>
            <div style={{ display: 'flex', gap: 6 }}>
              {['before', 'after', 'damage', 'receipt'].map(t => (
                <button key={t} onClick={() => updatePhoto(viewing.id, { tag: t })}
                  style={{ padding: '6px 11px', borderRadius: 7, border: `1.5px solid ${viewing.tag === t ? '#14C6BF' : 'rgba(255,255,255,.25)'}`, background: viewing.tag === t ? '#14C6BF' : 'transparent', color: viewing.tag === t ? '#000' : '#fff', cursor: 'pointer', fontSize: 11, fontWeight: 700, textTransform: 'uppercase', letterSpacing: '.05em' }}>{t}</button>
              ))}
            </div>
            <input
              placeholder="Add caption…" value={viewing.caption || ''}
              onChange={e => { const v = e.target.value; setViewing(prev => ({ ...prev, caption: v })); updatePhoto(viewing.id, { caption: v }); }}
              style={{ flex: 1, minWidth: 180, padding: '8px 13px', borderRadius: 7, border: '1.5px solid rgba(255,255,255,.2)', background: 'rgba(255,255,255,.08)', color: '#fff', fontSize: 13, fontFamily: 'inherit', outline: 'none' }} />
          </div>
        </div>
      )}
    </div>
  );
}

// ─── INVOICES LIST VIEW (auto-generated + manual) ──────────────
function InvoicesView({ jobs }) {
  const [invoices, setInvoices] = React.useState(() => getInvoices());
  const [filter, setFilter] = React.useState('all');
  const [selected, setSelected] = React.useState(null);

  React.useEffect(() => { saveInvoices(invoices); }, [invoices]);

  // Sync: re-read on mount in case auto-invoices were created elsewhere
  React.useEffect(() => {
    const sync = () => setInvoices(getInvoices());
    window.addEventListener('storage', sync);
    const interval = setInterval(sync, 1500);
    return () => { window.removeEventListener('storage', sync); clearInterval(interval); };
  }, []);

  const filtered = invoices.filter(i => filter === 'all' ? true : i.status === filter);
  const totalOwed = invoices.filter(i => i.status === 'unpaid' || i.status === 'overdue').reduce((s, i) => s + (i.total - (i.paid || 0)), 0);
  const totalPaid = invoices.filter(i => i.status === 'paid').reduce((s, i) => s + i.total, 0);

  const markPaid = (id) => {
    setInvoices(prev => prev.map(i => i.id === id ? { ...i, status: 'paid', paid: i.total, paidDate: new Date().toISOString().split('T')[0] } : i));
    showToast('Invoice marked paid');
  };
  const deleteInv = (id) => {
    if (!confirm('Delete this invoice?')) return;
    setInvoices(prev => prev.filter(i => i.id !== id));
    setSelected(null);
  };

  const statusStyles = {
    unpaid: { bg: '#fef3c7', color: '#b45309', label: 'Unpaid' },
    paid: { bg: '#f0fdf4', color: '#16a34a', label: 'Paid' },
    overdue: { bg: '#fef2f2', color: '#dc2626', label: 'Overdue' },
  };

  const sel = invoices.find(i => i.id === selected);

  if (sel) {
    return <InvoiceDetail invoice={sel} onBack={() => setSelected(null)} onMarkPaid={() => markPaid(sel.id)} onDelete={() => deleteInv(sel.id)} />;
  }

  return (
    <div>
      <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start', marginBottom: 20, flexWrap: 'wrap', gap: 12 }}>
        <div>
          <h1 style={{ fontSize: 22, fontWeight: 900, fontFamily: 'Poppins', marginBottom: 2 }}>Invoices</h1>
          <p style={{ color: 'var(--muted)', fontSize: 14 }}>{invoices.length} total · auto-generated when jobs are marked complete</p>
        </div>
        <div style={{ display: 'flex', gap: 14 }}>
          <div style={{ padding: '10px 16px', background: '#fef3c7', borderRadius: 10, minWidth: 140 }}>
            <div style={{ fontSize: 10, fontWeight: 700, color: '#b45309', textTransform: 'uppercase', letterSpacing: '.08em' }}>Outstanding</div>
            <div style={{ fontSize: 20, fontWeight: 900, color: '#b45309', fontFamily: 'Poppins' }}>${totalOwed.toLocaleString()}</div>
          </div>
          <div style={{ padding: '10px 16px', background: '#f0fdf4', borderRadius: 10, minWidth: 140 }}>
            <div style={{ fontSize: 10, fontWeight: 700, color: '#16a34a', textTransform: 'uppercase', letterSpacing: '.08em' }}>Collected</div>
            <div style={{ fontSize: 20, fontWeight: 900, color: '#16a34a', fontFamily: 'Poppins' }}>${totalPaid.toLocaleString()}</div>
          </div>
        </div>
      </div>

      <div style={{ display: 'flex', gap: 6, marginBottom: 16 }}>
        {[['all', 'All'], ['unpaid', 'Unpaid'], ['paid', 'Paid'], ['overdue', 'Overdue']].map(([val, lbl]) => {
          const count = val === 'all' ? invoices.length : invoices.filter(i => i.status === val).length;
          return (
            <button key={val} onClick={() => setFilter(val)}
              style={{ padding: '6px 14px', borderRadius: 20, border: '1.5px solid ' + (filter === val ? 'var(--accent)' : 'var(--border)'), background: filter === val ? 'var(--accent-light)' : 'transparent', color: filter === val ? 'var(--accent-dark)' : 'var(--muted)', fontFamily: 'inherit', fontWeight: 600, fontSize: 12, cursor: 'pointer' }}>
              {lbl} <span style={{ opacity: .65 }}>({count})</span>
            </button>
          );
        })}
      </div>

      {filtered.length === 0 ? (
        <div style={{ background: 'var(--card)', borderRadius: 16, padding: '50px 30px', textAlign: 'center', border: '2px dashed var(--border)' }}>
          <div style={{ marginBottom: 10, display: 'flex', justifyContent: 'center' }}><Icon name="receipt" size={40} color="var(--accent)"/></div>
          <div style={{ fontWeight: 800, fontSize: 16, fontFamily: 'Poppins', marginBottom: 6 }}>No invoices yet</div>
          <div style={{ color: 'var(--muted)', fontSize: 13 }}>Complete a job on the Jobs Board and an invoice is created automatically.</div>
        </div>
      ) : (
        <div style={{ background: 'var(--card)', borderRadius: 14, border: '1px solid var(--border)', overflow: 'hidden' }}>
          <table style={{ width: '100%', borderCollapse: 'collapse', fontSize: 13 }}>
            <thead>
              <tr style={{ background: 'var(--bg)' }}>
                {['Invoice #', 'Customer', 'Job', 'Issued', 'Due', 'Amount', 'Status', ''].map(h => (
                  <th key={h} style={{ padding: '10px 14px', textAlign: 'left', fontSize: 10, fontWeight: 700, textTransform: 'uppercase', letterSpacing: '0.07em', color: 'var(--muted)' }}>{h}</th>
                ))}
              </tr>
            </thead>
            <tbody>
              {filtered.map((inv, i) => {
                const s = statusStyles[inv.status] || statusStyles.unpaid;
                const overdue = inv.status === 'unpaid' && new Date(inv.due) < new Date();
                return (
                  <tr key={inv.id} onClick={() => setSelected(inv.id)}
                    style={{ borderTop: '1px solid var(--border)', cursor: 'pointer', background: i % 2 === 0 ? 'transparent' : 'var(--bg)' }}
                    onMouseOver={e => e.currentTarget.style.background = 'var(--accent-light)'}
                    onMouseOut={e => e.currentTarget.style.background = i % 2 === 0 ? 'transparent' : 'var(--bg)'}>
                    <td style={{ padding: '12px 14px', fontWeight: 800, color: 'var(--accent)' }}>{inv.id}</td>
                    <td style={{ padding: '12px 14px', fontWeight: 700 }}>{inv.customer}</td>
                    <td style={{ padding: '12px 14px', fontSize: 12, color: 'var(--muted)' }}>{inv.jobId || '—'}</td>
                    <td style={{ padding: '12px 14px', fontSize: 12 }}>{fmtShortDate(inv.issued)}</td>
                    <td style={{ padding: '12px 14px', fontSize: 12, color: overdue ? '#dc2626' : 'var(--muted)', fontWeight: overdue ? 700 : 400 }}>{fmtShortDate(inv.due)}</td>
                    <td style={{ padding: '12px 14px', fontWeight: 800, color: 'var(--accent)' }}>${inv.total.toLocaleString()}</td>
                    <td style={{ padding: '12px 14px' }}>
                      <span style={{ background: s.bg, color: s.color, padding: '4px 10px', borderRadius: 20, fontSize: 11, fontWeight: 700 }}>{s.label}</span>
                    </td>
                    <td style={{ padding: '12px 14px' }}>
                      <span style={{ color: 'var(--accent)', fontWeight: 700, fontSize: 12 }}>Open →</span>
                    </td>
                  </tr>
                );
              })}
            </tbody>
          </table>
        </div>
      )}
    </div>
  );
}

function InvoiceDetail({ invoice, onBack, onMarkPaid, onDelete }) {
  const [shareUrl, setShareUrl] = React.useState(null);

  const share = () => {
    const url = createPortalLink('invoice', invoice);
    setShareUrl(url);
    try { navigator.clipboard.writeText(url); showToast('Link copied — send to customer'); } catch {}
  };

  return (
    <div>
      <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginBottom: 18, flexWrap: 'wrap', gap: 10 }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: 12 }}>
          <button onClick={onBack} style={{ padding: '7px 14px', borderRadius: 9, border: '1.5px solid var(--border)', background: 'transparent', cursor: 'pointer', fontFamily: 'inherit', fontWeight: 700, fontSize: 13 }}>← Back</button>
          <div>
            <h2 style={{ fontSize: 18, fontWeight: 900, fontFamily: 'Poppins' }}>{invoice.id} — {invoice.customer}</h2>
            <div style={{ fontSize: 12, color: 'var(--muted)' }}>Issued {fmtDate(invoice.issued)} · Due {fmtDate(invoice.due)}</div>
          </div>
        </div>
        <div style={{ display: 'flex', gap: 8 }}>
          <button onClick={share} style={{ padding: '8px 14px', borderRadius: 9, border: '1.5px solid var(--accent)', color: 'var(--accent-dark)', background: 'var(--accent-light)', cursor: 'pointer', fontWeight: 700, fontFamily: 'inherit', fontSize: 13, display: 'inline-flex', alignItems: 'center', gap: 5 }}><Icon name="paperclip" size={13}/> Share with Customer</button>
          {invoice.status !== 'paid' && (
            <button onClick={onMarkPaid} style={{ padding: '8px 14px', borderRadius: 9, background: '#16a34a', color: '#fff', border: 'none', cursor: 'pointer', fontWeight: 700, fontFamily: 'inherit', fontSize: 13, display: 'inline-flex', alignItems: 'center', gap: 5 }}><Icon name="check" size={13} color="#fff"/> Mark Paid</button>
          )}
          <button onClick={() => window.print()} style={{ padding: '8px 14px', borderRadius: 9, border: '1.5px solid var(--border)', background: 'transparent', cursor: 'pointer', fontFamily: 'inherit', fontWeight: 700, fontSize: 13, display: 'inline-flex', alignItems: 'center', gap: 5 }}><Icon name="file-text" size={13}/> Print</button>
          <button onClick={onDelete} style={{ padding: '8px 14px', borderRadius: 9, border: 'none', background: '#fee2e2', color: '#ef4444', cursor: 'pointer', fontFamily: 'inherit', fontWeight: 700, fontSize: 13 }}>Delete</button>
        </div>
      </div>

      {shareUrl && (
        <div style={{ padding: 14, background: 'var(--accent-light)', borderRadius: 12, marginBottom: 16, display: 'flex', alignItems: 'center', gap: 10, fontSize: 12, border: '1.5px solid var(--accent)' }}>
          <Icon name="paperclip" size={18} color="var(--accent)"/>
          <div style={{ flex: 1 }}>
            <div style={{ fontWeight: 700, marginBottom: 2, color: 'var(--accent-dark)' }}>Customer link ready — already copied to clipboard</div>
            <div style={{ fontSize: 11, fontFamily: 'monospace', color: 'var(--muted)', wordBreak: 'break-all' }}>{shareUrl}</div>
          </div>
        </div>
      )}

      <div className="print-doc" style={{ background: '#fff', borderRadius: 16, border: '1.5px solid var(--border)', padding: '36px 44px', maxWidth: 820, boxShadow: '0 4px 24px rgba(0,0,0,0.06)' }}>
        <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-start', marginBottom: 28, paddingBottom: 18, borderBottom: '2px solid var(--accent)' }}>
          <div style={{ display: 'flex', gap: 10, alignItems: 'center' }}>
            <div style={{ width: 38, height: 38, background: 'var(--accent)', borderRadius: 9, display: 'flex', alignItems: 'center', justifyContent: 'center' }}><Icon name="truck" size={22} color="#fff"/></div>
            <div>
              <div style={{ fontWeight: 900, fontSize: 19 }}>MaxAMove</div>
              <div style={{ fontSize: 10, color: '#999', letterSpacing: '.06em' }}>LICENSED & INSURED · MAXAMOVE.COM</div>
            </div>
          </div>
          <div style={{ textAlign: 'right' }}>
            <div style={{ fontSize: 26, fontWeight: 900, color: 'var(--accent)' }}>INVOICE</div>
            <div style={{ fontSize: 13, color: '#666', lineHeight: 1.7 }}>{invoice.id}<br />Issued: {fmtDate(invoice.issued)}<br />Due: {fmtDate(invoice.due)}</div>
          </div>
        </div>
        <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 28, marginBottom: 24 }}>
          <div>
            <div style={{ fontSize: 10, fontWeight: 800, color: '#999', letterSpacing: '.1em', marginBottom: 6 }}>BILL TO</div>
            <div style={{ fontWeight: 700, fontSize: 15 }}>{invoice.customer}</div>
            <div style={{ fontSize: 13, color: '#555' }}>{invoice.phone}</div>
          </div>
          <div>
            <div style={{ fontSize: 10, fontWeight: 800, color: '#999', letterSpacing: '.1em', marginBottom: 6 }}>JOB DETAILS</div>
            <div style={{ fontSize: 13, lineHeight: 1.7 }}>
              {invoice.jobId && <div><b>Job #:</b> {invoice.jobId}</div>}
              <div><b>Move Date:</b> {fmtDate(invoice.moveDate)}</div>
              <div><b>Route:</b> {invoice.from} → {invoice.to}</div>
            </div>
          </div>
        </div>
        <table style={{ width: '100%', borderCollapse: 'collapse', marginBottom: 20 }}>
          <thead>
            <tr style={{ background: '#f9f9f9', borderBottom: '2px solid #eee' }}>
              <th style={{ padding: '10px 14px', textAlign: 'left', fontSize: 10, fontWeight: 800, color: '#999', letterSpacing: '.08em' }}>DESCRIPTION</th>
              <th style={{ padding: '10px 14px', textAlign: 'right', fontSize: 10, fontWeight: 800, color: '#999', letterSpacing: '.08em' }}>QTY</th>
              <th style={{ padding: '10px 14px', textAlign: 'right', fontSize: 10, fontWeight: 800, color: '#999', letterSpacing: '.08em' }}>RATE</th>
              <th style={{ padding: '10px 14px', textAlign: 'right', fontSize: 10, fontWeight: 800, color: '#999', letterSpacing: '.08em' }}>AMOUNT</th>
            </tr>
          </thead>
          <tbody>
            {invoice.lineItems.map((li, i) => (
              <tr key={i} style={{ borderBottom: '1px solid #f0f0f0' }}>
                <td style={{ padding: '11px 14px', fontSize: 13 }}>{li.desc}</td>
                <td style={{ padding: '11px 14px', textAlign: 'right', fontSize: 13 }}>{li.qty}</td>
                <td style={{ padding: '11px 14px', textAlign: 'right', fontSize: 13 }}>${li.rate.toLocaleString()}</td>
                <td style={{ padding: '11px 14px', textAlign: 'right', fontSize: 13, fontWeight: 700 }}>${li.amount.toLocaleString()}</td>
              </tr>
            ))}
          </tbody>
        </table>
        <div style={{ display: 'flex', justifyContent: 'flex-end', marginBottom: 20 }}>
          <div style={{ minWidth: 260 }}>
            <div style={{ display: 'flex', justifyContent: 'space-between', padding: '6px 0', fontSize: 13 }}><span style={{ color: '#666' }}>Subtotal</span><span>${invoice.subtotal.toLocaleString()}</span></div>
            {invoice.tax > 0 && <div style={{ display: 'flex', justifyContent: 'space-between', padding: '6px 0', fontSize: 13 }}><span style={{ color: '#666' }}>Tax</span><span>${invoice.tax.toLocaleString()}</span></div>}
            <div style={{ display: 'flex', justifyContent: 'space-between', padding: '10px 0', marginTop: 6, borderTop: '2px solid var(--accent)', fontSize: 17, fontWeight: 900, color: 'var(--accent)' }}><span>Total Due</span><span>${invoice.total.toLocaleString()}</span></div>
          </div>
        </div>
        <div style={{ padding: '14px 16px', background: '#f9f9f9', borderRadius: 10, fontSize: 11, color: '#666', lineHeight: 1.7 }}>
          <b style={{ color: '#333' }}>Payment:</b> Due within 7 days of issue. Accepting cash, check, Zelle, Venmo, and all major credit cards. Questions? Reply to the email this invoice came in, or call the number above.
        </div>
      </div>
    </div>
  );
}

Object.assign(window, {
  showToast, createInvoiceFromJob, getInvoices, saveInvoices,
  getJobPhotos, saveJobPhotos, resizeImageFile,
  createPortalLink, JobPhotoGrid, InvoicesView,
});
