// emails.jsx — Emails section: trial template, individual send, batch send

const { useState: useEmail } = React;

const TRIAL_MERGE = ['{{student}}', '{{trial_date}}', '{{class}}', '{{campus}}', '{{tutor}}'];
const TRIAL_DEFAULT = {
  subject: "🎉 You're booked in — your free trial at The Mathologists",
  body: "Hi {{student}},\n\nWe're so glad you're coming in for a free trial lesson — our tutors can't wait to meet you! Everything you need to know is just below.\n\nIf anything comes up or you'd like to reschedule, simply reply to this email and we'll sort it out.",
};

// A batch picks a base set of STUDENTS by category; the Students/Parents/Both
// toggle then decides who actually gets emailed.
const BATCH_CATEGORIES = [
  { value: 'class',        label: 'By class',                needs: 'class'   },
  { value: 'course',       label: 'By course',               needs: 'course'  },
  { value: 'program',      label: 'By program type',         needs: 'program' },
  { value: 'all-enrolled', label: 'All enrolled students',   needs: null      },
  { value: 'handpicked',   label: 'Hand-picked students',    needs: 'pick'    },
  { value: 'everyone',     label: 'Everyone (all contacts)', needs: null      },
];

// Staff batches are kept entirely separate from customers — scoped by role.
const STAFF_SCOPES = [
  { value: 'all',       label: 'All staff',       test: () => true            },
  { value: 'tutors',    label: 'Tutors',          test: r => /tutor/i.test(r) },
  { value: 'markers',   label: 'Markers',         test: r => /marker/i.test(r) },
  { value: 'reception', label: 'Reception',       test: r => /reception/i.test(r) },
];

function staffContacts(scope) {
  const def = STAFF_SCOPES.find(s => s.value === scope) || STAFF_SCOPES[0];
  return SAMPLE_STAFF.filter(s => def.test(s.role)).map(s => ({ id: s.id, name: `${s.firstName} ${s.lastName}`, role: s.role, email: s.email }));
}

function programKeyOptions() {
  return [
    { value: 'term-inperson', label: 'Term · In-person' },
    { value: 'term-online',   label: 'Term · Online' },
    ...SAMPLE_HOLIDAY_PROGRAMS.filter(p => !p.archived).map(p => ({ value: `holiday:${p.id}`, label: `Holiday: ${p.shortName || p.name}` })),
  ];
}

// Base STUDENTS for a batch (before the recipient-type toggle is applied)
function baseStudents(b) {
  const enrolled = SAMPLE_STUDENTS.filter(s => s.status === 'enrolled');
  switch (b.category) {
    case 'class':  return SAMPLE_STUDENTS.filter(s => s.classId === b.classId);
    case 'course': return enrolled.filter(s => s.course === b.course);
    case 'program': {
      if (b.programKey === 'term-inperson') return enrolled.filter(s => { const c = SAMPLE_CLASSES.find(x => x.id === s.classId); return c && c.delivery !== 'online'; });
      if (b.programKey === 'term-online')   return enrolled.filter(s => { const c = SAMPLE_CLASSES.find(x => x.id === s.classId); return c && c.delivery === 'online'; });
      if (b.programKey && b.programKey.indexOf('holiday:') === 0) { const pid = b.programKey.slice(8); return SAMPLE_STUDENTS.filter(s => (s.holiday || []).some(h => h.status === 'active' && h.programId === pid)); }
      return [];
    }
    case 'all-enrolled': return enrolled;
    case 'handpicked':   return SAMPLE_STUDENTS.filter(s => (b.picked || []).indexOf(s.id) !== -1);
    case 'everyone':     return SAMPLE_STUDENTS;
    default:             return [];
  }
}

// Group base students into families (one parent + their children in the set)
function familiesOf(students) {
  const map = new Map();
  students.forEach(s => {
    const key = s.parentId || `solo-${s.id}`;
    if (!map.has(key)) map.set(key, { key, parent: SAMPLE_PARENTS.find(p => p.id === s.parentId) || null, students: [] });
    map.get(key).students.push(s);
  });
  return [...map.values()];
}

function EmailFooter({ sig, light }) {
  const line = light ? '#E8E4D6' : 'var(--border-soft)';
  const nameC = light ? '#1A1815' : 'var(--text-primary)';
  const subC = light ? '#8A8575' : 'var(--text-muted)';
  return (
    <div style={{ marginTop: '20px', paddingTop: '16px', borderTop: `1px solid ${line}`, display: 'flex', alignItems: 'center', gap: '12px' }}>
      <div style={{ width: 38, height: 38, borderRadius: '8px', background: '#1F4D3D', display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: '13px', fontWeight: 700, color: '#FBFAF6', flexShrink: 0 }}>TM</div>
      <div style={{ fontSize: '12px', lineHeight: 1.5 }}>
        <div style={{ fontWeight: 600, color: nameC }}>{sig.name}</div>
        <div style={{ color: subC }}>{sig.role} · The Mathologists</div>
        <div style={{ color: subC }}>{sig.email}{sig.phone ? ` · ${sig.phone}` : ''}</div>
      </div>
    </div>
  );
}

function EmailPreview({ to, subject, body, sig, attachments }) {
  return (
    <div style={{ borderRadius: '10px', overflow: 'hidden', border: '1px solid var(--border-default)', boxShadow: '0 10px 32px rgba(0,0,0,0.38)' }}>
      {/* Inbox bar (dark) */}
      <div style={{ padding: '10px 16px', borderBottom: '1px solid var(--border-soft)', background: 'var(--bg-surface-muted)' }}>
        <div style={{ fontSize: '12px', color: 'var(--text-muted)', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>To: <span style={{ color: 'var(--text-secondary)' }}>{to || '—'}</span></div>
        <div style={{ fontSize: '14px', fontWeight: 600, color: 'var(--text-primary)', marginTop: '3px' }}>{subject || '(no subject)'}</div>
      </div>

      {/* Light branded email — slim letterhead (a quieter variation of the trial email) */}
      <div style={{ background: '#FAF9F5' }}>
        <div style={{ background: '#FBFAF6', borderBottom: '2px solid #1F4D3D', padding: '16px 28px', display: 'flex', alignItems: 'center', gap: '12px' }}>
          <div style={{ width: 34, height: 34, borderRadius: '8px', background: '#1F4D3D', display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: '13px', fontWeight: 700, color: '#FBFAF6', flexShrink: 0 }}>TM</div>
          <div>
            <div style={{ fontSize: '15px', fontWeight: 700, color: '#1A1815', letterSpacing: '-0.01em' }}>The Mathologists</div>
            <div style={{ fontSize: '11px', color: '#8A8575' }}>Parramatta · Bella Vista</div>
          </div>
        </div>
        <div style={{ padding: '22px 28px' }}>
          <div style={{ fontSize: '14px', color: '#3A352E', whiteSpace: 'pre-wrap', lineHeight: 1.65 }}>{body || '(empty message)'}</div>
          {attachments && attachments.length > 0 && (
            <div style={{ marginTop: '16px', display: 'flex', flexWrap: 'wrap', gap: '8px' }}>
              {attachments.map(a => <AttachmentChip key={a.id} a={a} light />)}
            </div>
          )}
          <EmailFooter sig={sig} light />
        </div>
      </div>
    </div>
  );
}

// Polished, branded trial email — rendered light (like a real inbox) with a
// header banner, a tidy details card and a warm tone.
function TrialEmailPreview({ subject, body, details, sig }) {
  const row = (label, value, last) => (
    <div style={{ display: 'flex', justifyContent: 'space-between', gap: '12px', padding: '11px 0', borderBottom: last ? 'none' : '1px solid #ECE7D8' }}>
      <span style={{ fontSize: '13px', color: '#8A8575', fontWeight: 500 }}>{label}</span>
      <span style={{ fontSize: '13px', color: '#1A1815', fontWeight: 600, textAlign: 'right' }}>{value || '—'}</span>
    </div>
  );
  return (
    <div style={{ borderRadius: '12px', overflow: 'hidden', border: '1px solid var(--border-default)', boxShadow: '0 10px 32px rgba(0,0,0,0.4)' }}>
      {/* Inbox subject line */}
      <div style={{ padding: '10px 16px', background: 'var(--bg-surface-muted)', borderBottom: '1px solid var(--border-soft)', fontSize: '12px', color: 'var(--text-muted)', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>
        Subject: <span style={{ color: 'var(--text-secondary)', fontWeight: 600 }}>{subject || '(no subject)'}</span>
      </div>

      {/* The email itself — light, branded */}
      <div style={{ background: '#FAF9F5' }}>
        <div style={{ background: '#1F4D3D', padding: '30px 28px 26px', textAlign: 'center' }}>
          <div style={{ width: 46, height: 46, borderRadius: '12px', background: 'rgba(255,255,255,0.12)', border: '1px solid rgba(255,255,255,0.25)', display: 'inline-flex', alignItems: 'center', justifyContent: 'center', fontSize: '16px', fontWeight: 700, color: '#FBFAF6', marginBottom: '14px' }}>TM</div>
          <div style={{ fontSize: '21px', fontWeight: 700, color: '#FBFAF6', letterSpacing: '-0.01em' }}>You're booked in! 🎉</div>
          <div style={{ fontSize: '13px', color: 'rgba(251,250,246,0.82)', marginTop: '5px' }}>Your free trial at The Mathologists</div>
        </div>

        <div style={{ padding: '26px 28px' }}>
          <div style={{ fontSize: '14px', color: '#3A352E', whiteSpace: 'pre-wrap', lineHeight: 1.65 }}>{body}</div>

          {/* Details card */}
          <div style={{ marginTop: '20px', background: '#FBFAF6', border: '1px solid #E8E4D6', borderRadius: '10px', padding: '4px 16px 8px', boxShadow: '0 1px 2px rgba(0,0,0,0.04)' }}>
            <div style={{ fontSize: '11px', fontWeight: 700, letterSpacing: '0.06em', textTransform: 'uppercase', color: '#1F4D3D', padding: '12px 0 2px' }}>Your trial details</div>
            {row('📅  Date', details.date)}
            {row('📚  Class', details.cls)}
            {row('📍  Campus', details.campus)}
            {row('👤  Tutor', details.tutor, true)}
          </div>

          {/* What to bring */}
          <div style={{ marginTop: '16px', display: 'flex', gap: '10px', background: 'rgba(31,77,61,0.06)', border: '1px solid rgba(31,77,61,0.15)', borderRadius: '8px', padding: '12px 14px' }}>
            <span style={{ fontSize: '15px', lineHeight: 1.4 }}>✏️</span>
            <span style={{ fontSize: '12.5px', color: '#3A352E', lineHeight: 1.5 }}>Please arrive <strong>10 minutes early</strong> and bring a notebook and pen — that's all you need!</span>
          </div>

          {/* Sign-off */}
          <div style={{ textAlign: 'center', marginTop: '22px' }}>
            <span style={{ display: 'inline-block', background: '#1F4D3D', color: '#FBFAF6', fontSize: '14px', fontWeight: 600, padding: '11px 24px', borderRadius: '8px' }}>We can't wait to see you 👋</span>
          </div>

          {/* Signature footer (light) */}
          <div style={{ marginTop: '26px', paddingTop: '18px', borderTop: '1px solid #E8E4D6', display: 'flex', alignItems: 'center', gap: '12px' }}>
            <div style={{ width: 38, height: 38, borderRadius: '8px', background: '#1F4D3D', display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: '13px', fontWeight: 700, color: '#FBFAF6', flexShrink: 0 }}>TM</div>
            <div style={{ fontSize: '12px', lineHeight: 1.5 }}>
              <div style={{ fontWeight: 600, color: '#1A1815' }}>{sig.name}</div>
              <div style={{ color: '#8A8575' }}>{sig.role} · The Mathologists</div>
              <div style={{ color: '#8A8575' }}>{sig.email}{sig.phone ? ` · ${sig.phone}` : ''}</div>
            </div>
          </div>
        </div>
      </div>
    </div>
  );
}

function fmtBytes(b) { return b < 1024 ? `${b} B` : b < 1048576 ? `${Math.round(b / 1024)} KB` : `${(b / 1048576).toFixed(1)} MB`; }

// Attachment thumbnail/chip used in the email preview
function AttachmentChip({ a, light }) {
  const bg = light ? '#FBFAF6' : 'var(--bg-surface-muted)';
  const bd = light ? '#E8E4D6' : 'var(--border-default)';
  const iconBg = light ? '#F0ECE0' : 'var(--bg-elevated)';
  const nameC = light ? '#1A1815' : 'var(--text-primary)';
  const subC = light ? '#8A8575' : 'var(--text-muted)';
  return (
    <div style={{ display: 'flex', alignItems: 'center', gap: '8px', background: bg, border: `1px solid ${bd}`, borderRadius: '6px', padding: '5px 10px 5px 5px', maxWidth: '210px' }}>
      {a.url
        ? <img src={a.url} alt={a.name} style={{ width: 30, height: 30, borderRadius: '4px', objectFit: 'cover', flexShrink: 0 }} />
        : <span style={{ width: 30, height: 30, borderRadius: '4px', background: iconBg, display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0, fontSize: '14px' }}>📄</span>}
      <div style={{ minWidth: 0 }}>
        <div style={{ fontSize: '12px', color: nameC, overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{a.name}</div>
        <div style={{ fontSize: '10px', color: subC }}>{fmtBytes(a.size)}</div>
      </div>
    </div>
  );
}

// "Attach files & images" control with previews + remove
function Attachments({ files, setFiles }) {
  const ref = React.useRef(null);
  const onPick = e => {
    const added = Array.from(e.target.files || []).map(f => ({
      id: `${f.name}_${f.size}_${Math.random().toString(36).slice(2, 7)}`,
      name: f.name, size: f.size, type: f.type,
      url: f.type && f.type.indexOf('image/') === 0 ? URL.createObjectURL(f) : null,
    }));
    setFiles(fs => [...fs, ...added]);
    if (e.target) e.target.value = '';
  };
  return (
    <div>
      <input ref={ref} type="file" multiple style={{ display: 'none' }} onChange={onPick} />
      <button onClick={() => ref.current && ref.current.click()}
        style={{ display: 'inline-flex', alignItems: 'center', gap: '6px', background: 'var(--bg-surface-muted)', border: '1px solid var(--border-default)', borderRadius: '6px', padding: '7px 12px', fontSize: '12px', color: 'var(--text-secondary)', cursor: 'pointer', fontFamily: 'inherit' }}>
        <svg width="13" height="13" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M21.44 11.05l-9.19 9.19a6 6 0 0 1-8.49-8.49l9.19-9.19a4 4 0 0 1 5.66 5.66l-9.2 9.19a2 2 0 0 1-2.83-2.83l8.49-8.48" /></svg>
        Attach files &amp; images
      </button>
      {files.length > 0 && (
        <div style={{ display: 'flex', flexWrap: 'wrap', gap: '8px', marginTop: '10px' }}>
          {files.map(f => (
            <div key={f.id} style={{ display: 'flex', alignItems: 'center', gap: '8px', background: 'var(--bg-surface-muted)', border: '1px solid var(--border-default)', borderRadius: '6px', padding: '5px 8px 5px 5px' }}>
              {f.url
                ? <img src={f.url} alt={f.name} style={{ width: 28, height: 28, borderRadius: '4px', objectFit: 'cover', flexShrink: 0 }} />
                : <span style={{ width: 28, height: 28, borderRadius: '4px', background: 'var(--bg-elevated)', display: 'flex', alignItems: 'center', justifyContent: 'center', flexShrink: 0, fontSize: '13px' }}>📄</span>}
              <div style={{ minWidth: 0, maxWidth: '140px' }}>
                <div style={{ fontSize: '12px', color: 'var(--text-primary)', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{f.name}</div>
                <div style={{ fontSize: '10px', color: 'var(--text-muted)' }}>{fmtBytes(f.size)}</div>
              </div>
              <button onClick={() => setFiles(fs => fs.filter(x => x.id !== f.id))} style={{ background: 'none', border: 'none', color: 'var(--text-muted)', cursor: 'pointer', fontSize: '15px', lineHeight: 1, fontFamily: 'inherit', flexShrink: 0 }}>×</button>
            </div>
          ))}
        </div>
      )}
    </div>
  );
}

function EmailsSection() {
  const [mode,  setMode]  = useEmail('trial');
  const sig = CURRENT_USER;  // signature footer comes from the signed-in receptionist's profile
  const [trial, setTrial] = useEmail(TRIAL_DEFAULT);
  const [indivDomain, setIndivDomain] = useEmail('customers');
  const [indiv, setIndiv] = useEmail({ toId: '', subject: '', body: '' });
  const [batch, setBatch] = useEmail({ domain: 'customers', staffScope: 'all', category: 'all-enrolled', classId: '', course: 'YR11 ADVN', programKey: 'term-inperson', picked: [], type: 'both', subject: '', body: '' });
  const [pickSearch, setPickSearch] = useEmail('');
  const [toast, setToast] = useEmail('');
  const [indivFiles, setIndivFiles] = useEmail([]);
  const [batchFiles, setBatchFiles] = useEmail([]);
  const [excluded, setExcluded]     = useEmail(() => new Set());
  const [reviewOpen, setReviewOpen] = useEmail(false);
  const [indivSearch, setIndivSearch] = useEmail('');
  const flash = msg => { setToast(msg); setTimeout(() => setToast(''), 2500); };
  // Reset exclusions whenever the audience changes
  React.useEffect(() => { setExcluded(new Set()); setReviewOpen(false); }, [batch.domain, batch.staffScope, batch.category, batch.classId, batch.course, batch.programKey, batch.type, (batch.picked || []).length]);

  const card = { background: 'var(--bg-surface)', border: '1px solid var(--border-soft)', borderRadius: '8px', padding: '18px' };
  const lbl  = { fontSize: '12px', color: 'var(--text-muted)', display: 'block', marginBottom: '4px' };
  const inp  = { width: '100%', background: 'var(--bg-surface-muted)', border: '1px solid var(--border-default)', borderRadius: '4px', padding: '8px 10px', fontSize: '13px', color: 'var(--text-primary)', fontFamily: 'inherit', outline: 'none' };
  const head = { fontSize: '11px', fontWeight: 600, letterSpacing: '0.05em', textTransform: 'uppercase', color: 'var(--text-muted)', marginBottom: '12px' };
  const seg  = on => ({ padding: '6px 14px', fontSize: '13px', fontWeight: on ? 600 : 500, fontFamily: 'inherit', cursor: 'pointer',
    background: on ? 'var(--bg-surface)' : 'transparent', color: on ? 'var(--text-primary)' : 'var(--text-secondary)',
    border: '1px solid', borderColor: on ? 'var(--border-default)' : 'transparent', borderRadius: '6px' });

  // Sample values for the trial-template preview
  const SAMPLE = { '{{student}}': 'Sarah Nguyen', '{{trial_date}}': 'Thu 22 May, 4:30pm', '{{class}}': 'Wed 4:30–6:30pm · YR11 ADVN', '{{campus}}': 'Parramatta', '{{tutor}}': 'Jamie Lee' };
  const merge = text => (text || '').replace(/\{\{[a-z_]+\}\}/g, m => (SAMPLE[m] !== undefined ? SAMPLE[m] : m));

  const customerContacts = [
    ...SAMPLE_STUDENTS.map(s => ({ id: s.id, name: `${s.firstName} ${s.lastName}`, role: 'Student', email: s.email })),
    ...SAMPLE_PARENTS.map(p  => ({ id: p.id, name: `${p.firstName} ${p.lastName}`, role: 'Parent', email: p.email })),
  ];
  const indivStaff = SAMPLE_STAFF.map(s => ({ id: s.id, name: `${s.firstName} ${s.lastName}`, role: s.role, email: s.email }));
  const contacts = indivDomain === 'staff' ? indivStaff : customerContacts;
  const indivContact = contacts.find(c => c.id === indiv.toId);
  const indivQuery = indivSearch.trim().toLowerCase();
  const indivMatches = indivQuery ? contacts.filter(c => c.name.toLowerCase().includes(indivQuery) || c.email.toLowerCase().includes(indivQuery)).slice(0, 30) : [];

  const isStaffBatch = batch.domain === 'staff';
  const catDef = BATCH_CATEGORIES.find(c => c.value === batch.category) || BATCH_CATEGORIES[0];
  const base = isStaffBatch ? [] : baseStudents(batch);
  const families = isStaffBatch ? [] : familiesOf(base);
  const wantStudents = batch.type !== 'parents';
  const wantParents  = batch.type !== 'students';
  const totalStudents  = wantStudents ? base.length : 0;
  const totalParents   = wantParents ? families.filter(f => f.parent).length : 0;
  const activeStudents = wantStudents ? base.filter(s => !excluded.has(s.id)).length : 0;
  const activeParents  = wantParents ? families.filter(f => f.parent && !excluded.has(f.parent.id)).length : 0;
  // Family-grouped review only when emailing customers with "Both" selected.
  const isFamilyMode = !isStaffBatch && batch.type === 'both';
  // Flat recipient list: staff pool, or customer students/parents (no family grouping).
  const flatList = isStaffBatch
    ? staffContacts(batch.staffScope)
    : batch.type === 'parents'
      ? families.filter(f => f.parent).map(f => ({ id: f.parent.id, name: `${f.parent.firstName} ${f.parent.lastName}`, role: 'Parent', email: f.parent.email }))
      : base.map(s => ({ id: s.id, name: `${s.firstName} ${s.lastName}`, role: 'Student', email: s.email }));
  const staffActive = isStaffBatch ? flatList.filter(r => !excluded.has(r.id)).length : 0;
  const recCount = isStaffBatch ? staffActive : activeStudents + activeParents;
  const totalRecipients = isStaffBatch ? flatList.length : totalStudents + totalParents;
  const excludedCount = totalRecipients - recCount;
  const toggleExcluded = id => setExcluded(prev => { const n = new Set(prev); n.has(id) ? n.delete(id) : n.add(id); return n; });

  return (
    <div>
      <SectionHeader title="Emails" subtitle="Trial confirmations, one-off messages and batch sends — all with your signature footer" />

      {/* Signature footer — auto from the signed-in receptionist's profile */}
      <div style={{ ...card, marginBottom: '18px', display: 'flex', alignItems: 'center', gap: '12px' }}>
        <div style={{ width: 38, height: 38, borderRadius: '8px', background: '#1F4D3D', display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: '13px', fontWeight: 700, color: '#FBFAF6', flexShrink: 0 }}>TM</div>
        <div style={{ minWidth: 0 }}>
          <div style={{ fontSize: '11px', fontWeight: 600, letterSpacing: '0.05em', textTransform: 'uppercase', color: 'var(--text-muted)' }}>Signature footer · from your profile</div>
          <div style={{ fontSize: '13px', color: 'var(--text-primary)', marginTop: '3px' }}><strong>{sig.name}</strong> · {sig.role} · {sig.email}{sig.phone ? ` · ${sig.phone}` : ''}</div>
        </div>
        <span style={{ marginLeft: 'auto', fontSize: '11px', color: 'var(--text-muted)', flexShrink: 0 }}>Auto-added to every email</span>
      </div>

      {/* Mode switch */}
      <div style={{ display: 'inline-flex', gap: '4px', background: 'var(--bg-surface-muted)', border: '1px solid var(--border-soft)', borderRadius: '8px', padding: '3px', marginBottom: '18px' }}>
        <button style={seg(mode === 'trial')}      onClick={() => setMode('trial')}>Trial email template</button>
        <button style={seg(mode === 'individual')} onClick={() => setMode('individual')}>Send individual</button>
        <button style={seg(mode === 'batch')}      onClick={() => setMode('batch')}>Batch send</button>
      </div>

      <div style={{ display: 'grid', gridTemplateColumns: '1fr 1fr', gap: '20px', alignItems: 'start' }}>
        {/* ── LEFT: editor ── */}
        <div style={card}>
          {mode === 'trial' && (
            <React.Fragment>
              <div style={head}>Trial email template</div>
              <div style={{ fontSize: '12px', color: 'var(--text-muted)', marginBottom: '12px' }}>Sent automatically when you click <strong style={{ color: 'var(--text-secondary)' }}>Send Trial Email</strong> on a customer. Merge fields fill in that student's details.</div>
              <label style={lbl}>Subject</label>
              <input value={trial.subject} onChange={e => setTrial(t => ({ ...t, subject: e.target.value }))} style={{ ...inp, marginBottom: '12px' }} />
              <label style={lbl}>Body</label>
              <textarea value={trial.body} onChange={e => setTrial(t => ({ ...t, body: e.target.value }))} rows={12} style={{ ...inp, resize: 'vertical', lineHeight: 1.55, marginBottom: '10px' }} />
              <div style={{ fontSize: '11px', color: 'var(--text-muted)', marginBottom: '6px' }}>Insert a merge field:</div>
              <div style={{ display: 'flex', flexWrap: 'wrap', gap: '6px' }}>
                {TRIAL_MERGE.map(m => (
                  <button key={m} onClick={() => setTrial(t => ({ ...t, body: t.body + (!t.body || t.body.endsWith('\n') || t.body.endsWith(' ') ? '' : ' ') + m }))}
                    style={{ background: 'var(--bg-surface-muted)', border: '1px solid var(--border-default)', borderRadius: '4px', padding: '4px 8px', fontSize: '11px', fontFamily: 'ui-monospace, monospace', color: 'var(--text-secondary)', cursor: 'pointer' }}>{m}</button>
                ))}
              </div>
              <div style={{ display: 'flex', justifyContent: 'flex-end', marginTop: '14px' }}>
                <Button variant="primary" onClick={() => flash('Trial email template saved')}>Save template</Button>
              </div>
            </React.Fragment>
          )}

          {mode === 'individual' && (
            <React.Fragment>
              <div style={head}>Send an individual email</div>
              <label style={lbl}>Recipient type</label>
              <div style={{ display: 'inline-flex', gap: '4px', background: 'var(--bg-surface-muted)', border: '1px solid var(--border-soft)', borderRadius: '7px', padding: '3px', marginBottom: '12px' }}>
                {[['customers', 'Customers'], ['staff', 'Staff']].map(([v, l]) => (
                  <button key={v} onClick={() => { if (indivDomain !== v) { setIndivDomain(v); setIndiv(x => ({ ...x, toId: '' })); setIndivSearch(''); } }} style={seg(indivDomain === v)}>{l}</button>
                ))}
              </div>
              <label style={lbl}>To</label>
              {indivContact ? (
                <div style={{ display: 'flex', alignItems: 'center', gap: '10px', background: 'var(--bg-surface-muted)', border: '1px solid var(--border-default)', borderRadius: '4px', padding: '8px 10px', marginBottom: '12px' }}>
                  <div style={{ flex: 1, minWidth: 0 }}>
                    <div style={{ fontSize: '13px', color: 'var(--text-primary)' }}>{indivContact.name} <span style={{ fontSize: '11px', color: 'var(--text-muted)' }}>· {indivContact.role}</span></div>
                    <div style={{ fontSize: '11px', color: 'var(--text-muted)', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{indivContact.email}</div>
                  </div>
                  <button onClick={() => setIndiv(x => ({ ...x, toId: '' }))} style={{ background: 'none', border: '1px solid var(--border-default)', borderRadius: '5px', padding: '4px 10px', fontSize: '12px', color: 'var(--text-secondary)', cursor: 'pointer', fontFamily: 'inherit', flexShrink: 0 }}>Change</button>
                </div>
              ) : (
                <div style={{ position: 'relative', marginBottom: '12px' }}>
                  <Icon name="search" size={14} color="var(--text-muted)" style={{ position: 'absolute', left: 10, top: '50%', transform: 'translateY(-50%)' }} />
                  <input value={indivSearch} onChange={e => setIndivSearch(e.target.value)} placeholder={`Search ${indivDomain === 'staff' ? 'staff' : 'students & parents'} by name or email…`} style={{ ...inp, paddingLeft: '32px' }} />
                  {indivQuery && (
                    <div style={{ position: 'absolute', top: 'calc(100% + 4px)', left: 0, right: 0, zIndex: 60, background: 'var(--bg-elevated)', border: '1px solid var(--border-default)', borderRadius: '6px', boxShadow: '0 8px 24px rgba(0,0,0,0.5)', padding: '4px', maxHeight: '260px', overflowY: 'auto' }}>
                      {indivMatches.length === 0 && <div style={{ padding: '8px 10px', fontSize: '12px', color: 'var(--text-muted)' }}>No matches</div>}
                      {indivMatches.map(c => (
                        <div key={c.id} onClick={() => { setIndiv(x => ({ ...x, toId: c.id })); setIndivSearch(''); }}
                          style={{ padding: '7px 10px', borderRadius: '4px', cursor: 'pointer' }}
                          onMouseEnter={e => e.currentTarget.style.background = 'rgba(255,255,255,0.06)'}
                          onMouseLeave={e => e.currentTarget.style.background = 'transparent'}>
                          <div style={{ fontSize: '13px', color: 'var(--text-primary)' }}>{c.name} <span style={{ fontSize: '11px', color: 'var(--text-muted)' }}>· {c.role}</span></div>
                          <div style={{ fontSize: '11px', color: 'var(--text-muted)', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{c.email}</div>
                        </div>
                      ))}
                    </div>
                  )}
                </div>
              )}
              <label style={lbl}>Subject</label>
              <input value={indiv.subject} onChange={e => setIndiv(x => ({ ...x, subject: e.target.value }))} style={{ ...inp, marginBottom: '12px' }} />
              <label style={lbl}>Message</label>
              <textarea value={indiv.body} onChange={e => setIndiv(x => ({ ...x, body: e.target.value }))} rows={10} style={{ ...inp, resize: 'vertical', lineHeight: 1.55 }} />
              <div style={{ marginTop: '12px' }}><Attachments files={indivFiles} setFiles={setIndivFiles} /></div>
              <div style={{ fontSize: '11px', color: 'var(--text-muted)', marginTop: '10px' }}>Your signature footer is added automatically.</div>
              <div style={{ display: 'flex', justifyContent: 'flex-end', marginTop: '14px' }}>
                <Button variant="primary" disabled={!indivContact} onClick={() => { flash(`Email sent to ${indivContact ? indivContact.email : ''}${indivFiles.length ? ` · ${indivFiles.length} attachment${indivFiles.length === 1 ? '' : 's'}` : ''}`); setIndiv({ toId: '', subject: '', body: '' }); setIndivFiles([]); }}>Send email</Button>
              </div>
            </React.Fragment>
          )}

          {mode === 'batch' && (
            <React.Fragment>
              <div style={head}>Batch send</div>

              {/* Customers vs Staff — kept entirely separate */}
              <label style={lbl}>Recipient type</label>
              <div style={{ display: 'inline-flex', gap: '4px', background: 'var(--bg-surface-muted)', border: '1px solid var(--border-soft)', borderRadius: '7px', padding: '3px', marginBottom: '14px' }}>
                {[['customers', 'Customers'], ['staff', 'Staff']].map(([v, l]) => (
                  <button key={v} onClick={() => setBatch(b => ({ ...b, domain: v }))} style={seg(batch.domain === v)}>{l}</button>
                ))}
              </div>

              {!isStaffBatch && (
                <React.Fragment>
                  <label style={lbl}>Audience</label>
                  <div style={{ marginBottom: '12px' }}>
                    <FormSelect value={batch.category} onChange={v => setBatch(b => ({ ...b, category: v }))} options={BATCH_CATEGORIES.map(c => ({ value: c.value, label: c.label }))} />
                  </div>

                  {catDef.needs === 'class' && (
                    <div style={{ marginBottom: '12px' }}>
                      <label style={lbl}>Class</label>
                      <FormSelect value={batch.classId} onChange={v => setBatch(b => ({ ...b, classId: v }))} placeholder="Select a class…"
                        options={SAMPLE_CLASSES.filter(c => !c.archived).map(c => ({ value: c.id, label: `${classLabel(c)} · ${c.campus}` }))} />
                    </div>
                  )}
                  {catDef.needs === 'course' && (
                    <div style={{ marginBottom: '12px' }}>
                      <label style={lbl}>Course</label>
                      <FormSelect value={batch.course} onChange={v => setBatch(b => ({ ...b, course: v }))}
                        options={['YR09', 'YR10', 'YR11 STD', 'YR11 ADVN', 'YR11 EXT1', 'YR12 STD', 'YR12 ADVN', 'YR12 EXT1', 'YR12 EXT2']} />
                    </div>
                  )}
                  {catDef.needs === 'program' && (
                    <div style={{ marginBottom: '12px' }}>
                      <label style={lbl}>Program</label>
                      <FormSelect value={batch.programKey} onChange={v => setBatch(b => ({ ...b, programKey: v }))} options={programKeyOptions()} />
                    </div>
                  )}
                  {catDef.needs === 'pick' && (
                    <div style={{ marginBottom: '12px' }}>
                      <label style={lbl}>Choose students — {(batch.picked || []).length} picked</label>
                      <input value={pickSearch} onChange={e => setPickSearch(e.target.value)} placeholder="Search students…" style={{ ...inp, marginBottom: '8px' }} />
                      <div style={{ border: '1px solid var(--border-soft)', borderRadius: '6px', maxHeight: '180px', overflowY: 'auto' }}>
                        {SAMPLE_STUDENTS.filter(s => { const q = pickSearch.toLowerCase(); return !q || `${s.firstName} ${s.lastName}`.toLowerCase().includes(q); }).slice(0, 150).map((s, i) => {
                          const on = (batch.picked || []).indexOf(s.id) !== -1;
                          return (
                            <div key={s.id} style={{ display: 'flex', alignItems: 'center', gap: '10px', padding: '7px 10px', borderTop: i ? '1px solid var(--border-soft)' : 'none' }}>
                              <Checkbox checked={on} onChange={v => setBatch(b => ({ ...b, picked: v ? [...(b.picked || []), s.id] : (b.picked || []).filter(x => x !== s.id) }))} />
                              <span style={{ fontSize: '13px', color: 'var(--text-primary)' }}>{s.firstName} {s.lastName}</span>
                              <span style={{ fontSize: '11px', color: 'var(--text-muted)', marginLeft: 'auto' }}>{s.course} · {s.campus}</span>
                            </div>
                          );
                        })}
                      </div>
                    </div>
                  )}

                  {/* Recipient type */}
                  <label style={lbl}>Send to</label>
                  <div style={{ display: 'inline-flex', gap: '4px', background: 'var(--bg-surface-muted)', border: '1px solid var(--border-soft)', borderRadius: '7px', padding: '3px', marginBottom: '12px' }}>
                    {[['students', 'Students'], ['parents', 'Parents'], ['both', 'Both']].map(([v, l]) => (
                      <button key={v} onClick={() => setBatch(b => ({ ...b, type: v }))} style={seg(batch.type === v)}>{l}</button>
                    ))}
                  </div>
                </React.Fragment>
              )}

              {isStaffBatch && (
                <div style={{ marginBottom: '12px' }}>
                  <label style={lbl}>Staff group</label>
                  <FormSelect value={batch.staffScope} onChange={v => setBatch(b => ({ ...b, staffScope: v }))} options={STAFF_SCOPES.map(s => ({ value: s.value, label: s.label }))} />
                </div>
              )}

              {/* Recipient count + review */}
              <div style={{ display: 'flex', alignItems: 'center', gap: '10px', background: 'var(--bg-surface-muted)', border: '1px solid var(--border-soft)', borderRadius: reviewOpen ? '6px 6px 0 0' : '6px', padding: '10px 12px', marginBottom: reviewOpen ? 0 : '12px' }}>
                <Icon name={isStaffBatch ? 'staff' : 'customers'} size={15} color={isStaffBatch ? '#9B6AC0' : '#4A9B7E'} />
                <span style={{ fontSize: '13px', color: 'var(--text-secondary)', flex: 1 }}>
                  <strong style={{ color: 'var(--text-primary)' }}>{recCount}</strong> {isStaffBatch ? 'staff ' : ''}recipient{recCount === 1 ? '' : 's'}
                  {!isStaffBatch && (totalStudents || totalParents) ? ` · ${activeStudents} students, ${activeParents} parents` : ''}
                  {excludedCount > 0 ? <span style={{ color: '#B8922A' }}> · {excludedCount} excluded</span> : ''}
                </span>
                {(isFamilyMode ? families.length : flatList.length) > 0 && (
                  <button onClick={() => setReviewOpen(o => !o)} style={{ background: 'none', border: '1px solid var(--border-default)', borderRadius: '5px', padding: '4px 10px', fontSize: '12px', color: 'var(--text-secondary)', cursor: 'pointer', fontFamily: 'inherit', flexShrink: 0 }}>{reviewOpen ? 'Hide list' : 'Review & exclude'}</button>
                )}
              </div>
              {reviewOpen && (
                <div style={{ border: '1px solid var(--border-soft)', borderTop: 'none', borderRadius: '0 0 6px 6px', maxHeight: '300px', overflowY: 'auto', marginBottom: '12px' }}>
                  {isFamilyMode ? (
                    families.length === 0 ? (
                      <div style={{ padding: '20px', textAlign: 'center', fontSize: '12px', color: 'var(--text-muted)' }}>No recipients</div>
                    ) : families.map((f, fi) => {
                      const mids = [...f.students.map(s => s.id), ...(f.parent ? [f.parent.id] : [])];
                      const famIncluded = mids.some(id => !excluded.has(id));
                      const setFam = include => setExcluded(prev => { const n = new Set(prev); mids.forEach(id => (include ? n.delete(id) : n.add(id))); return n; });
                      const famName = f.parent ? `${f.parent.lastName} family` : `${(f.students[0] || {}).lastName || 'No'} family`;
                      return (
                        <div key={f.key} style={{ borderTop: fi ? '1px solid var(--border-soft)' : 'none', padding: '8px 12px' }}>
                          <div style={{ display: 'flex', alignItems: 'center', gap: '10px' }}>
                            <Checkbox checked={famIncluded} onChange={setFam} title="Include/exclude whole family" />
                            <span style={{ fontSize: '11px', fontWeight: 700, letterSpacing: '0.04em', textTransform: 'uppercase', color: 'var(--text-secondary)' }}>{famName}</span>
                            <span style={{ fontSize: '10px', color: 'var(--text-muted)', marginLeft: 'auto' }}>exclude whole family ↑</span>
                          </div>
                          <div style={{ paddingLeft: '26px', marginTop: '3px', display: 'flex', flexDirection: 'column', gap: '1px' }}>
                            {f.students.map(s => {
                              const inc = !excluded.has(s.id);
                              return (
                                <div key={s.id} style={{ display: 'flex', alignItems: 'center', gap: '10px', padding: '4px 0', opacity: inc ? 1 : 0.45 }}>
                                  <Checkbox checked={inc} onChange={() => toggleExcluded(s.id)} />
                                  <span style={{ fontSize: '13px', color: 'var(--text-primary)', textDecoration: inc ? 'none' : 'line-through' }}>{s.firstName} {s.lastName} <span style={{ fontSize: '11px', color: 'var(--text-muted)' }}>· Student</span></span>
                                  <span style={{ fontSize: '11px', color: 'var(--text-muted)', marginLeft: 'auto', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap', maxWidth: '42%' }}>{s.email}</span>
                                </div>
                              );
                            })}
                            {f.parent ? (
                              <div style={{ display: 'flex', alignItems: 'center', gap: '10px', padding: '4px 0', opacity: !excluded.has(f.parent.id) ? 1 : 0.45 }}>
                                <Checkbox checked={!excluded.has(f.parent.id)} onChange={() => toggleExcluded(f.parent.id)} />
                                <span style={{ fontSize: '13px', color: 'var(--text-primary)', textDecoration: !excluded.has(f.parent.id) ? 'none' : 'line-through' }}>{f.parent.firstName} {f.parent.lastName} <span style={{ fontSize: '11px', color: 'var(--text-muted)' }}>· Parent</span></span>
                                <span style={{ fontSize: '11px', color: 'var(--text-muted)', marginLeft: 'auto', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap', maxWidth: '42%' }}>{f.parent.email}</span>
                              </div>
                            ) : <div style={{ fontSize: '11px', color: 'var(--text-muted)', fontStyle: 'italic', padding: '2px 0' }}>No linked parent</div>}
                          </div>
                        </div>
                      );
                    })
                  ) : (
                    flatList.length === 0 ? (
                      <div style={{ padding: '20px', textAlign: 'center', fontSize: '12px', color: 'var(--text-muted)' }}>No recipients</div>
                    ) : flatList.map((r, i) => {
                      const inc = !excluded.has(r.id);
                      return (
                        <div key={r.id} style={{ display: 'flex', alignItems: 'center', gap: '10px', padding: '8px 12px', borderTop: i ? '1px solid var(--border-soft)' : 'none', opacity: inc ? 1 : 0.45 }}>
                          <Checkbox checked={inc} onChange={() => toggleExcluded(r.id)} />
                          <div style={{ flex: 1, minWidth: 0 }}>
                            <div style={{ fontSize: '13px', color: 'var(--text-primary)', textDecoration: inc ? 'none' : 'line-through' }}>{r.name} <span style={{ fontSize: '11px', color: 'var(--text-muted)' }}>· {r.role}</span></div>
                            <div style={{ fontSize: '11px', color: 'var(--text-muted)', overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap' }}>{r.email}</div>
                          </div>
                        </div>
                      );
                    })
                  )}
                </div>
              )}

              <label style={lbl}>Subject</label>
              <input value={batch.subject} onChange={e => setBatch(b => ({ ...b, subject: e.target.value }))} style={{ ...inp, marginBottom: '12px' }} />
              <label style={lbl}>Message</label>
              <textarea value={batch.body} onChange={e => setBatch(b => ({ ...b, body: e.target.value }))} rows={7} style={{ ...inp, resize: 'vertical', lineHeight: 1.55 }} />
              <div style={{ marginTop: '12px' }}><Attachments files={batchFiles} setFiles={setBatchFiles} /></div>
              <div style={{ display: 'flex', justifyContent: 'flex-end', marginTop: '14px' }}>
                <Button variant="primary" disabled={recCount === 0} onClick={() => flash(`Batch email queued to ${recCount} recipient${recCount === 1 ? '' : 's'}${batchFiles.length ? ` · ${batchFiles.length} attachment${batchFiles.length === 1 ? '' : 's'}` : ''}`)}>Send to {recCount}</Button>
              </div>
            </React.Fragment>
          )}
        </div>

        {/* ── RIGHT: live preview ── */}
        <div>
          <div style={{ fontSize: '11px', fontWeight: 600, letterSpacing: '0.05em', textTransform: 'uppercase', color: 'var(--text-muted)', marginBottom: '10px' }}>Preview</div>
          {mode === 'trial'      && <TrialEmailPreview sig={sig} subject={merge(trial.subject)} body={merge(trial.body)} details={{ date: SAMPLE['{{trial_date}}'], cls: SAMPLE['{{class}}'], campus: SAMPLE['{{campus}}'], tutor: SAMPLE['{{tutor}}'] }} />}
          {mode === 'individual' && <EmailPreview sig={sig} to={indivContact ? indivContact.email : '—'} subject={indiv.subject} body={indiv.body} attachments={indivFiles} />}
          {mode === 'batch'      && <EmailPreview sig={sig} to={`${recCount} ${isStaffBatch ? 'staff ' : ''}recipient${recCount === 1 ? '' : 's'}`} subject={batch.subject} body={batch.body} attachments={batchFiles} />}
        </div>
      </div>

      {toast && (
        <div style={{ position: 'fixed', bottom: '24px', left: '50%', transform: 'translateX(-50%)', zIndex: 1000,
          background: 'var(--bg-elevated)', border: '1px solid rgba(74,155,126,0.4)', color: '#4A9B7E', borderRadius: '8px',
          padding: '10px 18px', fontSize: '13px', fontWeight: 500, boxShadow: '0 8px 24px rgba(0,0,0,0.4)' }}>
          ✓ {toast}
        </div>
      )}
    </div>
  );
}

Object.assign(window, { EmailsSection });
