// admin-sheets.jsx — Modal sheets for admin write actions
// All sheets share a right-side panel shell.

function SheetShell({ theme, title, subtitle, onClose, children, footer }) {
  return (
    <>
      <div onClick={onClose} style={{
        position: 'fixed', inset: 0, background: 'rgba(8,18,40,0.45)',
        zIndex: 200,
      }}/>
      <div style={{
        position: 'fixed', top: 0, right: 0, bottom: 0,
        width: 'min(520px, 96vw)',
        background: theme.canvas, zIndex: 201,
        display: 'flex', flexDirection: 'column',
        boxShadow: '-20px 0 60px rgba(0,0,0,0.25)',
      }}>
        <div style={{
          padding: '18px 24px 14px',
          borderBottom: `1px solid ${theme.rule}`,
          display: 'flex', alignItems: 'center', justifyContent: 'space-between',
          background: theme.raised,
        }}>
          <div>
            <div style={{ fontSize: 10, color: theme.inkMute, fontWeight: 600, letterSpacing: 1.6, textTransform: 'uppercase' }}>{subtitle || 'Action'}</div>
            <h2 className="serif" style={{ fontSize: 22, fontWeight: 500, color: theme.ink, margin: '4px 0 0', letterSpacing: -0.3, lineHeight: 1.1 }}>{title}</h2>
          </div>
          <button onClick={onClose} style={{
            width: 32, height: 32, borderRadius: 8,
            background: theme.canvas2, border: `1px solid ${theme.rule}`,
            display: 'flex', alignItems: 'center', justifyContent: 'center',
          }}><Icon name="x" size={14} color={theme.ink}/></button>
        </div>
        <div className="scroll" style={{ flex: 1, overflowY: 'auto', padding: '20px 24px 24px' }}>
          {children}
        </div>
        {footer && (
          <div style={{
            padding: '14px 24px',
            borderTop: `1px solid ${theme.rule}`,
            background: theme.raised,
            display: 'flex', gap: 10, justifyContent: 'flex-end',
          }}>{footer}</div>
        )}
      </div>
    </>
  );
}

// ─────────────────────────────────────────────────────────────
// Form primitives
// ─────────────────────────────────────────────────────────────
function Field({ label, hint, children }) {
  return (
    <div style={{ marginBottom: 16 }}>
      <label style={{ display: 'block', fontSize: 11, fontWeight: 600, letterSpacing: 0.7, textTransform: 'uppercase', color: '#7A88A6', marginBottom: 6 }}>
        {label}
      </label>
      {children}
      {hint && <div style={{ fontSize: 11.5, color: '#7A88A6', marginTop: 5 }}>{hint}</div>}
    </div>
  );
}

function TextInput({ theme, value, onChange, placeholder, mono }) {
  return (
    <input
      value={value || ''} onChange={e => onChange(e.target.value)}
      placeholder={placeholder}
      style={{
        width: '100%', padding: '10px 12px',
        background: theme.raised, border: `1px solid ${theme.rule}`,
        borderRadius: 9, fontSize: 13.5, color: theme.ink,
        fontFamily: mono ? 'JetBrains Mono, monospace' : 'inherit',
        outline: 'none',
      }}
      onFocus={e => e.target.style.borderColor = theme.surface}
      onBlur={e => e.target.style.borderColor = theme.rule}
    />
  );
}

function TextArea({ theme, value, onChange, placeholder, rows = 4 }) {
  return (
    <textarea
      value={value || ''} onChange={e => onChange(e.target.value)}
      placeholder={placeholder}
      rows={rows}
      style={{
        width: '100%', padding: '10px 12px',
        background: theme.raised, border: `1px solid ${theme.rule}`,
        borderRadius: 9, fontSize: 13.5, color: theme.ink,
        fontFamily: 'inherit', resize: 'vertical',
        outline: 'none', lineHeight: 1.45,
      }}
      onFocus={e => e.target.style.borderColor = theme.surface}
      onBlur={e => e.target.style.borderColor = theme.rule}
    />
  );
}

function Select({ theme, value, onChange, options }) {
  return (
    <select
      value={value} onChange={e => onChange(e.target.value)}
      style={{
        width: '100%', padding: '10px 12px',
        background: theme.raised, border: `1px solid ${theme.rule}`,
        borderRadius: 9, fontSize: 13.5, color: theme.ink,
        outline: 'none', appearance: 'none',
        backgroundImage: `url("data:image/svg+xml;utf8,<svg xmlns='http://www.w3.org/2000/svg' viewBox='0 0 24 24' fill='none' stroke='%23667' stroke-width='2'><path d='M5 9l7 7 7-7'/></svg>")`,
        backgroundRepeat: 'no-repeat', backgroundPosition: 'right 12px center', backgroundSize: 14,
        paddingRight: 36,
      }}
    >
      {options.map(o => (
        <option key={o.value || o} value={o.value || o}>{o.label || o}</option>
      ))}
    </select>
  );
}

function PillSegment({ theme, value, onChange, options }) {
  return (
    <div style={{
      display: 'inline-flex', gap: 0,
      background: theme.canvas2, border: `1px solid ${theme.rule}`,
      borderRadius: 9, padding: 2,
    }}>
      {options.map(o => (
        <button key={o.value} onClick={() => onChange(o.value)} style={{
          padding: '7px 14px', borderRadius: 7,
          fontSize: 12.5, fontWeight: 600,
          background: value === o.value ? theme.surface : 'transparent',
          color:      value === o.value ? theme.onSurface : theme.inkDim,
        }}>{o.label}</button>
      ))}
    </div>
  );
}

// VisibilityToggle — the key UX for internal vs client-facing notes
function VisibilityToggle({ theme, value, onChange }) {
  const options = [
    { value: 'public',   label: 'Internal + Client', icon: 'eye',    hint: 'Posted to the client\'s casefile' },
    { value: 'internal', label: 'Internal only',     icon: 'lock',   hint: 'Hidden from client; visible to team' },
  ];
  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
      {options.map(o => {
        const selected = value === o.value;
        return (
          <button key={o.value} onClick={() => onChange(o.value)} style={{
            display: 'flex', alignItems: 'center', gap: 12,
            padding: '12px 14px', borderRadius: 10,
            background: selected
              ? (o.value === 'internal' ? '#FAF6EC' : '#EAF1FB')
              : '#FFFFFF',
            border: selected
              ? `2px solid ${o.value === 'internal' ? '#D9B262' : '#4A85E0'}`
              : `1px solid ${theme.rule}`,
            textAlign: 'left', width: '100%',
            margin: 0, marginLeft: selected ? -1 : 0,
            cursor: 'pointer',
          }}>
            <div style={{
              width: 32, height: 32, borderRadius: 99, flexShrink: 0,
              background: o.value === 'internal' ? '#F0DDB2' : '#D9E5F4',
              color: o.value === 'internal' ? '#7A5A1B' : '#1F4A8B',
              display: 'flex', alignItems: 'center', justifyContent: 'center',
            }}><Icon name={o.icon} size={14} color={o.value === 'internal' ? '#7A5A1B' : '#1F4A8B'}/></div>
            <div style={{ flex: 1 }}>
              <div style={{ fontSize: 13.5, fontWeight: 600, color: theme.ink }}>{o.label}</div>
              <div style={{ fontSize: 11.5, color: theme.inkMute, marginTop: 2 }}>{o.hint}</div>
            </div>
            {selected && <Icon name="check" size={16} color={o.value === 'internal' ? '#7A5A1B' : '#1F4A8B'} strokeWidth={2.5}/>}
          </button>
        );
      })}
    </div>
  );
}

// ─────────────────────────────────────────────────────────────
// 1) ADD EVENT
// ─────────────────────────────────────────────────────────────
function AddEventSheet({ theme, client, onClose }) {
  const [type, setType]             = React.useState('negotiation');
  const [title, setTitle]           = React.useState('');
  const [body, setBody]             = React.useState('');
  const [amount, setAmount]         = React.useState('');
  const [relatedLender, setLender]  = React.useState('');
  const [visibility, setVisibility] = React.useState('public');
  const [busy, setBusy]             = React.useState(false);
  const [errMsg, setErrMsg]         = React.useState(null);

  const lenders = lendersForClient(client.id);

  const submit = async () => {
    setErrMsg(null);
    if (!title.trim()) { setErrMsg('Title is required.'); return; }
    setBusy(true);
    try {
      const amt = parseCurrency(amount);
      await api.admin.createEvent(client.id, {
        type, title: title.trim(),
        body: body.trim() || null,
        amount: (type === 'offer' || type === 'settled') ? amt : null,
        lender_id: relatedLender || null,
        visibility,
      });
      onClose(true);
    } catch (e) {
      setErrMsg(e.message || 'Failed to post event.');
    } finally { setBusy(false); }
  };

  return (
    <SheetShell theme={theme} title="Add casefile event" subtitle={`${client.name} · ${client.code}`} onClose={() => onClose(false)}
      footer={<>
        <button onClick={() => onClose(false)} style={btn(theme, 'ghost')}>Cancel</button>
        <button onClick={submit} disabled={busy} style={btn(theme, 'primary', busy)}>{busy ? 'Posting…' : 'Post event'}</button>
      </>}
    >
      <Field label="Event type">
        <PillSegment theme={theme} value={type} onChange={setType} options={[
          { value: 'negotiation', label: 'Negotiation' },
          { value: 'offer',       label: 'Offer' },
          { value: 'settled',     label: 'Settled' },
          { value: 'message',     label: 'Note' },
          { value: 'document',    label: 'Document' },
        ]}/>
      </Field>

      <Field label="Related lender (optional)">
        <Select theme={theme} value={relatedLender} onChange={setLender} options={[
          { value: '', label: '— No lender association —' },
          ...lenders.map(l => ({ value: l.id, label: l.name })),
        ]}/>
      </Field>

      <Field label="Title" hint="Shown as the headline in the casefile.">
        <TextInput theme={theme} value={title} onChange={setTitle} placeholder="e.g. Kanon Funding underwriter assigned"/>
      </Field>

      <Field label="Detail">
        <TextArea theme={theme} value={body} onChange={setBody} rows={5} placeholder="What happened, next steps, expectations…"/>
      </Field>

      {(type === 'offer' || type === 'settled') && (
        <Field label="Amount" hint="Settlement / offer amount in USD.">
          <TextInput theme={theme} value={amount} onChange={setAmount} placeholder="$0" mono/>
        </Field>
      )}

      <div style={{ marginTop: 22, paddingTop: 18, borderTop: `1px dashed ${theme.rule}` }}>
        <Field label="Visibility" hint="You can change this later. Internal notes never appear on the client's app.">
          <VisibilityToggle theme={theme} value={visibility} onChange={setVisibility}/>
        </Field>
      </div>

      {errMsg && <SheetErrorBanner message={errMsg}/>}
    </SheetShell>
  );
}

// ─────────────────────────────────────────────────────────────
// 2) UPLOAD DOCUMENT
// ─────────────────────────────────────────────────────────────
function UploadDocSheet({ theme, client, onClose }) {
  const [file, setFile]             = React.useState(null);
  const [folder, setFolder]         = React.useState('Settlement Agreements');
  const [tag, setTag]               = React.useState('');
  const [visibility, setVisibility] = React.useState('public');
  const [notify, setNotify]         = React.useState(true);
  const [busy, setBusy]             = React.useState(false);
  const [errMsg, setErrMsg]         = React.useState(null);

  const submit = async () => {
    setErrMsg(null);
    if (!file) { setErrMsg('Please choose a PDF.'); return; }
    if (file.size > 25 * 1024 * 1024) { setErrMsg('File too large (max 25 MB).'); return; }
    setBusy(true);
    try {
      await api.admin.uploadDocument(client.id, file, { folder, tag: tag || null, visibility });
      // (Notify-client toggle is a UX placeholder for now — backend doesn't yet send
      // notifications; you can wire it later by adding a column or calling email API.)
      onClose(true);
    } catch (e) {
      setErrMsg(e.message || 'Upload failed.');
    } finally { setBusy(false); }
  };

  return (
    <SheetShell theme={theme} title="Upload document" subtitle={`${client.name} · ${client.code}`} onClose={() => onClose(false)}
      footer={<>
        <button onClick={() => onClose(false)} style={btn(theme, 'ghost')}>Cancel</button>
        <button onClick={submit} disabled={busy} style={btn(theme, 'primary', busy)}>{busy ? 'Uploading…' : 'Upload'}</button>
      </>}
    >
      <Field label="File">
        <label htmlFor="dl-file-pick" style={{
          display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 8,
          padding: '32px 24px', borderRadius: 12,
          background: theme.raised, border: `2px dashed ${theme.rule}`,
          cursor: 'pointer',
        }}>
          <Icon name="upload" size={20} color={theme.inkDim}/>
          <div style={{ fontSize: 13, fontWeight: 600, color: theme.ink }}>
            {file ? file.name : 'Drag PDF here or click to browse'}
          </div>
          <div style={{ fontSize: 11, color: theme.inkMute }}>PDF up to 25 MB</div>
          <input
            id="dl-file-pick" type="file" accept=".pdf" hidden
            onChange={e => setFile(e.target.files[0])}
          />
        </label>
      </Field>

      <Field label="Folder">
        <Select theme={theme} value={folder} onChange={setFolder} options={[
          'Settlement Agreements', 'Statements', 'ID & Compliance', 'Internal Notes',
        ]}/>
      </Field>

      <Field label="Tag (optional)">
        <Select theme={theme} value={tag} onChange={setTag} options={[
          { value: '', label: '— None —' },
          'Signed', 'Submitted', 'Draft', 'Countersigned', 'Hardship', 'Internal',
        ]}/>
      </Field>

      <div style={{ marginTop: 22, paddingTop: 18, borderTop: `1px dashed ${theme.rule}` }}>
        <Field label="Visibility" hint="Internal documents stay in your team's vault.">
          <VisibilityToggle theme={theme} value={visibility} onChange={setVisibility}/>
        </Field>
      </div>

      {visibility === 'public' && (
        <label style={{
          display: 'flex', alignItems: 'center', gap: 10,
          padding: '12px 14px', borderRadius: 10,
          background: theme.canvas2, border: `1px solid ${theme.rule}`,
          marginTop: 6, cursor: 'pointer',
        }}>
          <input type="checkbox" checked={notify} onChange={e => setNotify(e.target.checked)} style={{ accentColor: theme.surface, width: 15, height: 15 }}/>
          <div>
            <div style={{ fontSize: 13, fontWeight: 600, color: theme.ink }}>Notify client</div>
            <div style={{ fontSize: 11.5, color: theme.inkMute, marginTop: 2 }}>Send a push + email when this is uploaded.</div>
          </div>
        </label>
      )}

      {errMsg && <SheetErrorBanner message={errMsg}/>}
    </SheetShell>
  );
}

// ─────────────────────────────────────────────────────────────
// 3) LOG OFFER
// ─────────────────────────────────────────────────────────────
function LogOfferSheet({ theme, client, onClose }) {
  const lenders = lendersForClient(client.id);
  const [lenderId, setLenderId] = React.useState(lenders[0]?.id || '');
  const [amount, setAmount]     = React.useState('');
  const [kind, setKind]         = React.useState('lump');
  const [installments, setInst] = React.useState('4');
  const [expires, setExpires]   = React.useState('');
  const [note, setNote]         = React.useState('');
  const [visibility, setVis]    = React.useState('public');
  const [requireSig, setSig]    = React.useState(true);
  const [busy, setBusy]         = React.useState(false);
  const [errMsg, setErrMsg]     = React.useState(null);

  const lender = lenders.find(l => l.id === lenderId);
  const balance = lender?.balance || 0;
  const amt = parseCurrency(amount);
  const discount = balance > 0 ? Math.max(0, Math.round(100 - (amt / balance) * 100)) : 0;

  const submit = async () => {
    setErrMsg(null);
    if (!lenderId) { setErrMsg('Pick a lender.'); return; }
    if (!amt) { setErrMsg('Enter the settlement amount.'); return; }
    setBusy(true);
    try {
      // Update the lender's settlement + status
      await api.admin.updateLender(lenderId, {
        settlement_amount: amt,
        status: 'Offer Received',
      });
      // Log an event for the casefile
      const detail = [
        `${kind === 'lump' ? 'Lump sum' : `${installments} installments`} of $${amt.toLocaleString()}`,
        expires && `Expires ${expires}`,
        note,
      ].filter(Boolean).join('\n\n');
      await api.admin.createEvent(client.id, {
        type: 'offer',
        title: `${lender?.name || 'Lender'} submitted ${kind === 'lump' ? 'a lump-sum offer' : 'an installment offer'}`,
        body: detail,
        amount: balance > 0 ? balance - amt : null,
        lender_id: lenderId,
        visibility,
      });
      onClose(true);
    } catch (e) {
      setErrMsg(e.message || 'Failed to record offer.');
    } finally { setBusy(false); }
  };

  return (
    <SheetShell theme={theme} title="Log lender offer" subtitle={`${client.name} · ${client.code}`} onClose={() => onClose(false)}
      footer={<>
        <button onClick={() => onClose(false)} style={btn(theme, 'ghost')}>Cancel</button>
        <button onClick={submit} disabled={busy} style={btn(theme, 'primary', busy)}>{busy ? 'Recording…' : 'Record offer'}</button>
      </>}
    >
      <Field label="Lender">
        <Select theme={theme} value={lenderId} onChange={setLenderId} options={lenders.map(l => ({ value: l.id, label: l.name }))}/>
      </Field>

      <Field label="Offer type">
        <PillSegment theme={theme} value={kind} onChange={setKind} options={[
          { value: 'lump',        label: 'Lump sum' },
          { value: 'installment', label: 'Installments' },
        ]}/>
      </Field>

      <Field label="Settlement amount" hint={amt > 0 && balance > 0 ? `${discount}% discount off $${balance.toLocaleString()} balance` : ''}>
        <TextInput theme={theme} value={amount} onChange={setAmount} placeholder="$0" mono/>
      </Field>

      {kind === 'installment' && (
        <Field label="Number of installments">
          <TextInput theme={theme} value={installments} onChange={setInst} placeholder="4" mono/>
        </Field>
      )}

      <Field label="Offer expires">
        <TextInput theme={theme} value={expires} onChange={setExpires} placeholder="e.g. Jun 7, 2026"/>
      </Field>

      <Field label="Negotiation note">
        <TextArea theme={theme} value={note} onChange={setNote} placeholder="Underwriter rationale, leverage points, fallback positions…"/>
      </Field>

      <label style={{
        display: 'flex', alignItems: 'center', gap: 10,
        padding: '12px 14px', borderRadius: 10,
        background: theme.canvas2, border: `1px solid ${theme.rule}`,
        marginBottom: 16, cursor: 'pointer',
      }}>
        <input type="checkbox" checked={requireSig} onChange={e => setSig(e.target.checked)} style={{ accentColor: theme.surface, width: 15, height: 15 }}/>
        <div>
          <div style={{ fontSize: 13, fontWeight: 600, color: theme.ink }}>Require client approval</div>
          <div style={{ fontSize: 11.5, color: theme.inkMute, marginTop: 2 }}>Client must approve before funds disburse from reserve.</div>
        </div>
      </label>

      <div style={{ marginTop: 12, paddingTop: 18, borderTop: `1px dashed ${theme.rule}` }}>
        <Field label="Visibility">
          <VisibilityToggle theme={theme} value={visibility} onChange={setVis}/>
        </Field>
      </div>

      {errMsg && <SheetErrorBanner message={errMsg}/>}
    </SheetShell>
  );
}

// ─────────────────────────────────────────────────────────────
// 4) UPDATE PAYMENT
// ─────────────────────────────────────────────────────────────
function UpdatePaymentSheet({ theme, client, onClose }) {
  const [mode, setMode]     = React.useState('schedule');
  const [date, setDate]     = React.useState(client.nextDate || '');
  const [amount, setAmount] = React.useState(client.nextPayment ? `$${client.nextPayment}` : '');
  const [reason, setReason] = React.useState('');
  const [busy, setBusy]     = React.useState(false);
  const [errMsg, setErrMsg] = React.useState(null);

  const submit = async () => {
    setErrMsg(null);
    setBusy(true);
    try {
      const amt = parseCurrency(amount);
      const iso = date ? parseDateLoose(date) : null;
      if (mode === 'schedule') {
        if (!iso || !amt) throw new Error('Date and amount required.');
        await api.admin.createPayment(client.id, { date_scheduled: iso, amount: amt, status: 'Scheduled', internal_note: reason || null });
        await api.admin.updateClient(client.id, { next_payment_amount: amt, next_payment_date: iso });
      } else if (mode === 'amount') {
        if (!amt) throw new Error('Amount required.');
        await api.admin.updateClient(client.id, { next_payment_amount: amt });
      } else if (mode === 'mark') {
        if (!iso || !amt) throw new Error('Date and amount required.');
        await api.admin.createPayment(client.id, {
          date_scheduled: iso, amount: amt, status: 'Posted',
          date_settled: iso, internal_note: reason || null,
        });
      } else if (mode === 'fail') {
        // Find most recent scheduled payment for this client and mark failed
        const upcoming = paymentsForClient(client.id).find(p => p.status === 'Scheduled');
        if (!upcoming) throw new Error('No scheduled payment to mark failed.');
        await api.admin.updatePayment(upcoming.id, { status: 'Failed', internal_note: reason || null });
      }
      onClose(true);
    } catch (e) {
      setErrMsg(e.message || 'Failed.');
    } finally { setBusy(false); }
  };

  return (
    <SheetShell theme={theme} title="Update payment" subtitle={`${client.name} · ${client.code}`} onClose={() => onClose(false)}
      footer={<>
        <button onClick={() => onClose(false)} style={btn(theme, 'ghost')}>Cancel</button>
        <button onClick={submit} disabled={busy} style={btn(theme, 'primary', busy)}>{busy ? 'Saving…' : 'Save'}</button>
      </>}
    >
      <Field label="Action">
        <PillSegment theme={theme} value={mode} onChange={setMode} options={[
          { value: 'schedule',  label: 'Reschedule' },
          { value: 'amount',    label: 'Change amount' },
          { value: 'mark',      label: 'Mark posted' },
          { value: 'fail',      label: 'Mark failed' },
        ]}/>
      </Field>

      {(mode === 'schedule' || mode === 'mark') && (
        <Field label="Date">
          <TextInput theme={theme} value={date} onChange={setDate} placeholder="Jun 1, 2026"/>
        </Field>
      )}
      {(mode === 'amount' || mode === 'schedule' || mode === 'mark') && (
        <Field label="Amount">
          <TextInput theme={theme} value={amount} onChange={setAmount} placeholder="$2,450" mono/>
        </Field>
      )}

      <Field label="Reason / internal note">
        <TextArea theme={theme} value={reason} onChange={setReason} placeholder="Why this change? Stays internal."/>
      </Field>

      <div style={{
        marginTop: 10, padding: '11px 13px',
        background: '#FAF6EC', border: '1px solid #E2C77B',
        borderRadius: 9, display: 'flex', alignItems: 'flex-start', gap: 10,
      }}>
        <Icon name="info" size={14} color="#7A5A1B"/>
        <div style={{ fontSize: 11.5, color: '#7A5A1B', lineHeight: 1.5 }}>
          The client will see a "Payment updated" notification, but the internal reason stays in your team's audit log.
        </div>
      </div>
    </SheetShell>
  );
}

// ─────────────────────────────────────────────────────────────
// 5) ASSIGN REP
// ─────────────────────────────────────────────────────────────
function AssignRepSheet({ theme, client, onClose }) {
  const [picked, setPicked] = React.useState(client.rep);
  const [busy, setBusy]     = React.useState(false);
  const [errMsg, setErrMsg] = React.useState(null);

  const submit = async () => {
    setErrMsg(null);
    if (!picked) { setErrMsg('Pick a specialist.'); return; }
    setBusy(true);
    try {
      await api.admin.updateClient(client.id, { rep_user_id: picked });
      const rep = repById(picked);
      await api.admin.createEvent(client.id, {
        type: 'message',
        title: `${rep?.name || 'New specialist'} assigned to your case`,
        body: 'Your new specialist will reach out to introduce themselves shortly.',
        visibility: 'public',
      });
      onClose(true);
    } catch (e) {
      setErrMsg(e.message || 'Failed to assign.');
    } finally { setBusy(false); }
  };

  return (
    <SheetShell theme={theme} title="Assign specialist" subtitle={`${client.name} · ${client.code}`} onClose={() => onClose(false)}
      footer={<>
        <button onClick={() => onClose(false)} style={btn(theme, 'ghost')}>Cancel</button>
        <button onClick={submit} disabled={busy} style={btn(theme, 'primary', busy)}>{busy ? 'Assigning…' : 'Assign'}</button>
      </>}
    >
      <div style={{ fontSize: 12.5, color: theme.inkMute, marginBottom: 14 }}>
        Reassigning will move this casefile to the selected specialist's queue. The client will be notified by email.
      </div>

      <div style={{ display: 'flex', flexDirection: 'column', gap: 8 }}>
        {ADMIN_REPS.map(r => {
          const selected = picked === r.id;
          const full = r.caseload >= r.capacity;
          const pto = r.status === 'pto';
          return (
            <button key={r.id} onClick={() => setPicked(r.id)} disabled={pto} style={{
              display: 'flex', alignItems: 'center', gap: 12,
              padding: '12px 14px', borderRadius: 10,
              background: selected ? '#EAF1FB' : theme.raised,
              border: selected ? `2px solid ${theme.surface}` : `1px solid ${theme.rule}`,
              marginLeft: selected ? -1 : 0,
              opacity: pto ? 0.5 : 1,
              textAlign: 'left', cursor: pto ? 'not-allowed' : 'pointer',
            }}>
              <div style={{
                width: 38, height: 38, borderRadius: 99,
                background: `linear-gradient(135deg, ${theme.accent.solid}, ${theme.accent.ink})`,
                color: '#fff', fontSize: 12, fontWeight: 700,
                display: 'flex', alignItems: 'center', justifyContent: 'center',
                fontFamily: 'Newsreader, serif', flexShrink: 0,
              }}>{r.initials}</div>
              <div style={{ flex: 1 }}>
                <div style={{ display: 'flex', alignItems: 'center', gap: 8 }}>
                  <span style={{ fontSize: 13.5, fontWeight: 600, color: theme.ink }}>{r.name}</span>
                  {pto && <span style={{ fontSize: 10, fontWeight: 700, color: '#7A2E11', background: '#F5DFC9', padding: '2px 6px', borderRadius: 99 }}>PTO</span>}
                  {full && <span style={{ fontSize: 10, fontWeight: 700, color: '#7A4A0F', background: '#FEEFD9', padding: '2px 6px', borderRadius: 99 }}>FULL</span>}
                </div>
                <div style={{ fontSize: 11.5, color: theme.inkMute, marginTop: 2 }}>{r.role}</div>
              </div>
              <div style={{ textAlign: 'right' }}>
                <div className="tnum" style={{ fontSize: 12, fontWeight: 600, color: theme.ink }}>
                  {r.caseload}/{r.capacity}
                </div>
                <div style={{ fontSize: 10, color: theme.inkMute, marginTop: 2 }}>caseload</div>
              </div>
              {selected && <Icon name="check" size={16} color={theme.surface} strokeWidth={2.5}/>}
            </button>
          );
        })}
      </div>

      {errMsg && <SheetErrorBanner message={errMsg}/>}
    </SheetShell>
  );
}

// ─────────────────────────────────────────────────────────────
// 6) NEW CLIENT (intake)
// ─────────────────────────────────────────────────────────────
function NewClientSheet({ theme, onClose }) {
  const [name, setName]   = React.useState('');
  const [biz, setBiz]     = React.useState('');
  const [email, setEmail] = React.useState('');
  const [phone, setPhone] = React.useState('');
  const [refSrc, setRef]  = React.useState('');
  const [rep, setRep]     = React.useState(ADMIN_REPS.find(r => r.role?.includes('Intake'))?.id || '');
  const [estDebt, setDbt] = React.useState('');
  const [busy, setBusy]   = React.useState(false);
  const [errMsg, setErrMsg] = React.useState(null);

  const submit = async () => {
    setErrMsg(null);
    if (!name.trim()) { setErrMsg('Owner name required.'); return; }
    if (!biz.trim())  { setErrMsg('Business name required.'); return; }
    if (!email.trim()) { setErrMsg('Email required.'); return; }
    setBusy(true);
    try {
      const r = await api.admin.createClient({
        name: name.trim(),
        business: biz.trim(),
        email: email.trim(),
        phone: phone.trim() || null,
        enrolled_amount: parseCurrency(estDebt) || 0,
        referral_source_id: refSrc || null,
        rep_user_id: rep || null,
      });
      // Refresh roster and switch to the new client
      onClose(r.id);
    } catch (e) {
      setErrMsg(e.message || 'Failed to create client.');
    } finally { setBusy(false); }
  };

  return (
    <SheetShell theme={theme} title="New client intake" subtitle="Create casefile" onClose={() => onClose(false)}
      footer={<>
        <button onClick={() => onClose(false)} style={btn(theme, 'ghost')}>Cancel</button>
        <button onClick={submit} disabled={busy} style={btn(theme, 'primary', busy)}>{busy ? 'Creating…' : 'Create file'}</button>
      </>}
    >
      <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 12 }}>
        <Field label="Owner name">
          <TextInput theme={theme} value={name} onChange={setName} placeholder="First Last"/>
        </Field>
        <Field label="Business">
          <TextInput theme={theme} value={biz} onChange={setBiz} placeholder="Company name"/>
        </Field>
      </div>
      <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: 12 }}>
        <Field label="Email">
          <TextInput theme={theme} value={email} onChange={setEmail} placeholder="owner@business.com"/>
        </Field>
        <Field label="Phone">
          <TextInput theme={theme} value={phone} onChange={setPhone} placeholder="+1 (555) 555-0100" mono/>
        </Field>
      </div>
      <Field label="Estimated enrolled debt" hint="Rough figure from discovery call; will be refined.">
        <TextInput theme={theme} value={estDebt} onChange={setDbt} placeholder="$0" mono/>
      </Field>
      <Field label="Referral source">
        <Select theme={theme} value={refSrc} onChange={setRef} options={[
          { value: '', label: '— Direct / no referral —' },
          ...REFERRAL_SOURCES.map(r => ({ value: r.id, label: r.name })),
        ]}/>
      </Field>
      <Field label="Assign intake specialist">
        <Select theme={theme} value={rep} onChange={setRep} options={ADMIN_REPS.map(r => ({
          value: r.id, label: `${r.name} — ${r.role}${r.status === 'pto' ? ' (PTO)' : ''}`,
        }))}/>
      </Field>

      {errMsg && <SheetErrorBanner message={errMsg}/>}
    </SheetShell>
  );
}

// ─────────────────────────────────────────────────────────────
// HELPERS
// ─────────────────────────────────────────────────────────────
function parseCurrency(input) {
  if (input == null) return 0;
  const cleaned = String(input).replace(/[^0-9.]/g, '');
  const n = parseFloat(cleaned);
  return Number.isFinite(n) ? n : 0;
}

// Parse loose date strings like "Jun 1, 2026" or "2026-06-01" → ISO8601
function parseDateLoose(input) {
  if (!input) return null;
  const t = Date.parse(input);
  if (Number.isFinite(t)) return new Date(t).toISOString();
  return null;
}

function SheetErrorBanner({ message }) {
  return (
    <div style={{
      marginTop: 14, padding: '10px 12px',
      background: '#FBE7E7', border: '1px solid #E6B5B5',
      borderRadius: 8, color: '#7A2E11',
      fontSize: 12.5, lineHeight: 1.4,
    }}>{message}</div>
  );
}

// shared button style
function btn(theme, kind, disabled) {
  const base = {
    padding: '10px 18px', borderRadius: 9,
    fontSize: 13, fontWeight: 600,
    opacity: disabled ? 0.6 : 1,
    cursor: disabled ? 'wait' : 'pointer',
  };
  if (kind === 'primary') return {
    ...base,
    background: theme.surface, color: theme.onSurface,
  };
  return {
    ...base, fontWeight: 500,
    background: 'transparent', color: theme.inkDim,
  };
}

Object.assign(window, {
  SheetShell, Field, TextInput, TextArea, Select, PillSegment, VisibilityToggle,
  AddEventSheet, UploadDocSheet, LogOfferSheet, UpdatePaymentSheet, AssignRepSheet, NewClientSheet,
  parseCurrency, parseDateLoose, SheetErrorBanner,
});
