// email.jsx — EMAIL module: compose (rich editor) / sent / templates / settings + widget.
const MAIL_APP = APPS.find(a => a.id === 'mail');

function RichEditor({ html, onInput, placeholder }) {
  const ref = React.useRef();
  React.useEffect(() => { if (ref.current && ref.current.innerHTML !== html) ref.current.innerHTML = html || ''; }, [html]);
  const cmd = (c, v) => { document.execCommand(c, false, v); ref.current.focus(); onInput(ref.current.innerHTML); };
  const Btn = ({ c, v, icon, title }) => <button type="button" className="iconbtn" title={title} onMouseDown={e => { e.preventDefault(); cmd(c, v); }}><i className={'bi ' + icon}></i></button>;
  return (
    <div className="editor-wrap">
      <div className="editor-toolbar">
        <Btn c="bold" icon="bi-type-bold" title="Bold" /><Btn c="italic" icon="bi-type-italic" title="Italic" /><Btn c="underline" icon="bi-type-underline" title="Underline" />
        <span className="sep"></span>
        <button type="button" className="iconbtn" title="Color" onMouseDown={e => e.preventDefault()} style={{ position:'relative' }}>
          <i className="bi bi-palette" style={{ color:'var(--primary)' }}></i>
          <input type="color" defaultValue="#1466E0" onChange={e => cmd('foreColor', e.target.value)} style={{ position:'absolute', inset:0, opacity:0, cursor:'pointer' }} />
        </button>
        <Btn c="insertUnorderedList" icon="bi-list-ul" title="Bullets" /><Btn c="insertOrderedList" icon="bi-list-ol" title="Numbered" />
        <span className="sep"></span>
        <button type="button" className="iconbtn" title="Link" onMouseDown={e => { e.preventDefault(); const u = prompt('URL:', 'https://'); if (u) cmd('createLink', u); }}><i className="bi bi-link-45deg"></i></button>
        <button type="button" className="iconbtn" title="Image" onMouseDown={e => { e.preventDefault(); cmd('insertHTML', '<div style="background:repeating-linear-gradient(135deg,#eee,#eee 8px,#f6f6f6 8px,#f6f6f6 16px);border:1px solid #ddd;border-radius:4px;height:90px;display:flex;align-items:center;justify-content:center;color:#999;font-family:monospace;font-size:11px;margin:6px 0">image-placeholder.png</div>'); }}><i className="bi bi-image"></i></button>
      </div>
      <div ref={ref} className="editor" contentEditable data-ph={placeholder} suppressContentEditableWarning
        onInput={e => onInput(e.currentTarget.innerHTML)} />
    </div>
  );
}

function MailCompose() {
  const p = usePortal();
  const { t, lang } = useLang();
  const toast = useToast();
  const [to, setTo] = React.useState(p.pendingData.mail?.to || []);
  const [cc, setCc] = React.useState(p.pendingData.mail?.cc || []);
  const [subject, setSubject] = React.useState(p.pendingData.mail?.subject || '');
  // Hiển thị chữ ký ngay trong nội dung khi soạn mới (để biết chính xác thông tin gửi đi);
  // nếu mở từ pending có sẵn body (vd gửi báo giá) thì dùng body đó.
  const sig = p.mailSettings.signature || '';
  const [body, setBody] = React.useState(p.pendingData.mail?.body || (sig ? '<p><br></p><p><br></p>' + sig : ''));
  // Đính kèm: nhận file thật truyền từ nơi khác (vd PDF báo giá) — chỉ giữ object có b64.
  const [attach, setAttach] = React.useState((p.pendingData.mail?.attach || []).filter(a => a && a.b64));
  const [quoteCode] = React.useState(p.pendingData.mail?.quoteCode || '');
  const [sending, setSending] = React.useState(false);
  const suggestions = CONTACTS.map(c => c.email);
  const validEmail = s => /^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(s);
  const realSend = !!(window.GMail && GMail.configured());
  const fileRef = React.useRef();
  const fmtSize = (n) => n < 1024 ? n + ' B' : n < 1048576 ? Math.round(n / 1024) + ' KB' : (n / 1048576).toFixed(1) + ' MB';
  const onFiles = (e) => {
    const files = [...(e.target.files || [])];
    e.target.value = '';
    files.forEach(file => {
      if (file.size > 8 * 1024 * 1024) { toast((lang === 'vi' ? 'Tệp quá lớn (>8MB): ' : 'File too large (>8MB): ') + file.name, 'error'); return; }
      const rd = new FileReader();
      rd.onload = () => { const b64 = String(rd.result).split(',')[1] || ''; setAttach(s => [...s, { name:file.name, type:file.type || 'application/octet-stream', size:file.size, b64 }]); };
      rd.readAsDataURL(file);
    });
  };
  React.useEffect(() => { if (p.pendingData.mail) p.clearPending(); }, []);

  const applyTemplate = (tpl) => { setSubject(tpl.subject); setBody(tpl.html + '<br>' + p.mailSettings.signature); };
  // Chèn chữ ký namecard (có QR vCard) của user hiện tại vào cuối nội dung.
  const insertNamecard = () => setBody(b => (b || '') + '<br>' + namecardEmailHTML(loadNamecard(p.me, p.branding), p.branding));
  const send = async () => {
    if (!to.length) { toast(lang === 'vi' ? 'Chưa có người nhận' : 'No recipient', 'error'); return; }
    if (!to.every(validEmail)) { toast(lang === 'vi' ? 'Email người nhận không hợp lệ' : 'Invalid recipient email', 'error'); return; }
    const subj = subject || '(no subject)';
    const html = body || '<p>(empty)</p>';
    if (realSend) {   // gửi THẬT qua Gmail bằng tài khoản đang đăng nhập
      setSending(true);
      try { await GMail.send({ to, cc, subject:subj, html, from:p.me.email, hint:p.me.email, attachments:attach }); }
      catch (e) { setSending(false); toast((lang === 'vi' ? 'Gửi thất bại: ' : 'Send failed: ') + (e.message || e), 'error'); return; }
      setSending(false);
    }
    p.addSentEmail({ id:'e' + Date.now(), to, cc, subject:subj, date:new Date().toISOString().slice(0, 16).replace('T', ' '), status:'sent', html, attach:attach.map(a => a.name), sentBy:p.me.email });
    toast(realSend ? (lang === 'vi' ? 'Đã gửi email qua Gmail' : 'Email sent via Gmail') : t('mail.sent.ok'), 'success');
    setTo([]); setCc([]); setSubject(''); setBody(''); setAttach([]);
    p.navigate({ name:'module', module:'mail', sub:'sent' });
  };

  return (
    <div className="page pagefade" style={{ maxWidth:880 }}>
      <div className="page-head"><div><h1>{t('mail.compose')}</h1><div className="sub">{realSend ? (lang === 'vi' ? 'Soạn và gửi email thật qua Gmail.' : 'Compose & send real email via Gmail.') : (lang === 'vi' ? 'Soạn và gửi email ra ngoài (mô phỏng).' : 'Compose & send external email (mock).')}</div></div></div>
      {quoteCode && <div className="card" style={{ marginBottom:12, background:'var(--accent-light)', borderColor:'color-mix(in srgb, var(--accent) 28%, transparent)' }}><div className="card-body flex g10 items-center" style={{ fontSize:'var(--fs-base)' }}>
        <i className="bi bi-receipt" style={{ color:'var(--accent)', fontSize:15 }}></i>
        <span>{lang === 'vi' ? 'Đang kèm báo giá ' : 'Attaching quote '}<span className="mono" style={{ fontWeight:600, color:'var(--accent)' }}>{quoteCode}</span>{lang === 'vi' ? ' — báo giá đã được đánh dấu “đã gửi”.' : ' — the quote is marked as sent.'}</span>
      </div></div>}
      <div className="card"><div className="card-body col g16">
        <Field label={t('mail.from')}><input className="input" value={p.me.email} disabled style={{ background:'var(--bg-sunken)' }} /></Field>
        <Field label={t('mail.to')}><ChipInput value={to} onChange={setTo} suggestions={suggestions} listId="to-sug" placeholder={lang === 'vi' ? 'Nhập email, Enter để thêm' : 'Type email, Enter to add'} /></Field>
        <Field label={t('mail.cc')}><ChipInput value={cc} onChange={setCc} suggestions={suggestions} listId="cc-sug" placeholder="Cc…" /></Field>
        <div className="flex g12 wrap items-start">
          <div className="grow" style={{ minWidth:220 }}><Field label={t('mail.subject')}><input className="input" value={subject} onChange={e => setSubject(e.target.value)} placeholder={lang === 'vi' ? 'Tiêu đề email' : 'Subject'} /></Field></div>
          <Field label={'\u00A0'}>
            <div className="flex items-center" style={{ height:'var(--control-h)' }}>
              <Popover align="right" width={230} button={({ toggle }) => <button className="btn" onClick={toggle}><i className="bi bi-file-earmark-richtext"></i>{t('mail.template')}</button>}>
                {({ close }) => (<>
                  <div className="menu-label">{t('mail.templates')}</div>
                  {p.templates.map(tpl => <button key={tpl.id} className="menu-item" onClick={() => { applyTemplate(tpl); close(); }}><i className="bi bi-envelope-paper"></i>{tpl.name[lang] || tpl.name.vi}</button>)}
                </>)}
              </Popover>
            </div>
          </Field>
        </div>
        <Field label={lang === 'vi' ? 'Nội dung' : 'Body'}><RichEditor html={body} onInput={setBody} placeholder={lang === 'vi' ? 'Nhập nội dung email…' : 'Write your email…'} /></Field>
        <div className="flex g8 items-center wrap">
          {attach.map((a, i) => <span key={i} className="badge badge-neutral"><i className="bi bi-paperclip"></i>{a.name} <span className="subtle">({fmtSize(a.size)})</span><button onClick={() => setAttach(s => s.filter((_, j) => j !== i))} style={{ border:'none', background:'none', marginLeft:2 }}><i className="bi bi-x"></i></button></span>)}
          <input ref={fileRef} type="file" multiple onChange={onFiles} style={{ display:'none' }} />
          <button className="btn btn-subtle btn-sm" onClick={() => fileRef.current && fileRef.current.click()}><i className="bi bi-paperclip"></i>{t('mail.attach')}</button>
          <button className="btn btn-subtle btn-sm" onClick={insertNamecard}><i className="bi bi-qr-code"></i>{lang === 'vi' ? 'Chèn chữ ký namecard' : 'Insert namecard'}</button>
        </div>
        <div className="flex justify-between items-center">
          <span className="subtle" style={{ fontSize:'var(--fs-sm)' }}><i className={'bi ' + (realSend ? 'bi-shield-check' : 'bi-shield-lock')} style={realSend ? { color:'var(--success)' } : null}></i> {realSend ? (lang === 'vi' ? 'Gửi thật từ ' : 'Sends from ') + p.me.email : (lang === 'vi' ? 'Chế độ mô phỏng — chưa cấu hình Gmail' : 'Mock mode — Gmail not configured')}</span>
          <button className="btn btn-primary btn-lg" onClick={send} disabled={sending}>{sending ? <><i className="bi bi-arrow-repeat spin"></i>{lang === 'vi' ? 'Đang gửi…' : 'Sending…'}</> : <><i className="bi bi-send"></i>{t('c.send')}</>}</button>
        </div>
      </div></div>
    </div>
  );
}

/* Mock inbox — hiển thị khi chưa cấu hình Gmail OAuth. Đã xóa email demo. */
const MOCK_INBOX = [];

function MailInbox() {
  const p = usePortal();
  const { t, lang } = useLang();
  const toast = useToast();
  const live = !!(window.GMail && GMail.configured());
  const [q, setQ] = React.useState('');
  const [flt, setFlt] = React.useState('');                 // '', 'is:unread', 'has:attachment'
  const [list, setList] = React.useState([]);
  const [loading, setLoading] = React.useState(false);
  const [err, setErr] = React.useState('');
  const [open, setOpen] = React.useState(null);             // mail chi tiết
  const [loadingMsg, setLoadingMsg] = React.useState(false);
  const splitRef = React.useRef(null);
  const [listW, setListW] = usePersist('mail-list-w', 380); // px; CSS min(...,50%) chốt trần

  // Kéo thanh phân cách: set CSS var trực tiếp khi kéo (không re-render), commit state lúc nhả.
  const startResize = (e) => {
    const el = splitRef.current; if (!el) return;
    e.preventDefault();
    const rect = el.getBoundingClientRect();
    const bar = e.currentTarget;
    let last = listW;
    const move = (ev) => {
      last = Math.max(240, Math.min(rect.width * 0.5, ev.clientX - rect.left));
      el.style.setProperty('--inbox-list-w', last + 'px');
    };
    const up = () => {
      window.removeEventListener('pointermove', move); window.removeEventListener('pointerup', up);
      document.body.style.cursor = ''; document.body.style.userSelect = '';
      bar.classList.remove('dragging');
      setListW(Math.round(last));
    };
    document.body.style.cursor = 'col-resize'; document.body.style.userSelect = 'none';
    bar.classList.add('dragging');
    window.addEventListener('pointermove', move); window.addEventListener('pointerup', up);
  };

  const buildQuery = () => [flt, q.trim()].filter(Boolean).join(' ');

  const load = React.useCallback(async (query) => {
    setErr(''); setLoading(true); setOpen(null);
    try {
      if (live) {
        const rows = await GMail.listInbox({ q: query, max: 25, hint: p.me.email });
        setList(rows);
      } else {
        // Mock: lọc client-side theo từ khóa + cờ.
        const term = q.trim().toLowerCase();
        let rows = MOCK_INBOX;
        if (flt === 'is:unread') rows = rows.filter(m => m.unread);
        if (flt === 'has:attachment') rows = rows.filter(m => m.hasAttach);
        if (term) rows = rows.filter(m => (m.subject + ' ' + m.from + ' ' + m.snippet).toLowerCase().includes(term));
        setList(rows);
      }
    } catch (e) {
      setErr(e.message || String(e)); setList([]);
    } finally { setLoading(false); }
  }, [live, q, flt, p.me.email]);

  React.useEffect(() => { load(buildQuery()); }, [flt]);     // tải lần đầu (flt='') + mỗi khi đổi bộ lọc

  const openMail = async (row) => {
    if (live) {
      setLoadingMsg(true);
      try { const full = await GMail.getMessage(row.id, p.me.email); setOpen({ ...row, ...full }); }
      catch (e) { toast((lang === 'vi' ? 'Không tải được email: ' : 'Failed to load: ') + (e.message || e), 'error'); }
      finally { setLoadingMsg(false); }
    } else {
      setOpen(row);
    }
    setList(rows => rows.map(m => m.id === row.id ? { ...m, unread:false } : m));
  };

  const reply = (m) => {
    const addr = (m.from.match(/<([^>]+)>/) || [null, m.from])[1];
    p.quick('mail', { to:[addr], subject:(/^re:/i.test(m.subject) ? '' : 'Re: ') + m.subject });
  };

  // Reply all: To = người gửi + mọi người trong To (trừ mình), Cc = Cc gốc (trừ mình, khử trùng).
  const EMAIL_RE = /[A-Za-z0-9._%+-]+@[A-Za-z0-9.-]+\.[A-Za-z]{2,}/g;
  const replyAllTargets = (m) => {
    const me = (p.me.email || '').toLowerCase();
    const seen = new Set();
    const uniq = (arr) => arr.filter(a => { const k = a.toLowerCase(); if (k === me || seen.has(k)) return false; seen.add(k); return true; });
    const to = uniq([...(String(m.from || '').match(EMAIL_RE) || []), ...(String(m.to || '').match(EMAIL_RE) || [])]);
    const cc = uniq(String(m.cc || '').match(EMAIL_RE) || []);
    return { to, cc };
  };
  const replyAll = (m) => {
    const { to, cc } = replyAllTargets(m);
    p.quick('mail', { to, cc, subject:(/^re:/i.test(m.subject) ? '' : 'Re: ') + m.subject });
  };

  const [dling, setDling] = React.useState('');               // attachmentId đang tải
  const downloadAttach = async (a) => {
    if (!live || !a.attachmentId) { toast(lang === 'vi' ? 'Không tải được (dữ liệu mẫu)' : 'Cannot download (sample data)', 'info'); return; }
    setDling(a.attachmentId);
    try {
      const b64url = await GMail.getAttachment(open.id, a.attachmentId, p.me.email);
      const bin = atob(b64url.replace(/-/g, '+').replace(/_/g, '/'));
      const bytes = new Uint8Array(bin.length);
      for (let i = 0; i < bin.length; i++) bytes[i] = bin.charCodeAt(i);
      const url = URL.createObjectURL(new Blob([bytes], { type: a.type || 'application/octet-stream' }));
      const link = document.createElement('a');
      link.href = url; link.download = a.name || 'attachment';
      document.body.appendChild(link); link.click(); link.remove();
      setTimeout(() => URL.revokeObjectURL(url), 2000);
    } catch (e) {
      toast((lang === 'vi' ? 'Tải đính kèm thất bại: ' : 'Download failed: ') + (e.message || e), 'error');
    } finally { setDling(''); }
  };

  const chip = (id, icon, label) => (
    <button className={'catchip' + (flt === id ? ' is-active' : '')} onClick={() => setFlt(flt === id ? '' : id)}>
      <i className={'bi ' + icon}></i>{label}
    </button>
  );

  return (
    <div className="page page-inbox pagefade">
      <div className="page-head inbox-head">
        <div><h1>{lang === 'vi' ? 'Hộp thư đến' : 'Inbox'}</h1>
          <div className="sub">{live ? (lang === 'vi' ? 'Đọc thư thật từ Gmail của bạn.' : 'Real mail from your Gmail.') : (lang === 'vi' ? 'Dữ liệu mẫu — bật Gmail để đọc thư thật.' : 'Sample data — enable Gmail to read real mail.')}</div>
        </div>
        <div className="flex g8 items-center">
          <form onSubmit={e => { e.preventDefault(); load(buildQuery()); }} className="flex g8 items-center">
            <div className="topsearch" style={{ background:'var(--bg)', border:'1px solid var(--border-strong)', width:260, maxWidth:'40vw' }}>
              <i className="bi bi-search"></i>
              <input value={q} onChange={e => setQ(e.target.value)} style={{ border:'none', outline:'none', background:'transparent', flex:1, font:'inherit', color:'var(--text)' }}
                placeholder={lang === 'vi' ? 'Tìm thư, from:, subject:…' : 'Search, from:, subject:…'} />
            </div>
            <button className="btn btn-primary" type="submit"><i className="bi bi-search"></i>{lang === 'vi' ? 'Tìm' : 'Search'}</button>
          </form>
          <button className="btn" onClick={() => load(buildQuery())} disabled={loading} title={lang === 'vi' ? 'Làm mới' : 'Refresh'}><i className={'bi bi-arrow-clockwise' + (loading ? ' spin' : '')}></i></button>
        </div>
      </div>

      <div className="catbar inbox-filters">
        {chip('', 'bi-inbox', lang === 'vi' ? 'Tất cả' : 'All')}
        {chip('is:unread', 'bi-envelope', lang === 'vi' ? 'Chưa đọc' : 'Unread')}
        {chip('has:attachment', 'bi-paperclip', lang === 'vi' ? 'Có đính kèm' : 'Has attachment')}
      </div>

      {err && <div className="card inbox-err"><div className="card-body flex g8 items-center"><i className="bi bi-exclamation-triangle" style={{ color:'var(--danger)' }}></i>{err}</div></div>}

      <div className="inbox-split" ref={splitRef} style={{ '--inbox-list-w': listW + 'px' }}>
        <div className="card inbox-list">
          {loading && <div className="empty" style={{ padding:24 }}><i className="bi bi-arrow-repeat spin"></i> {lang === 'vi' ? 'Đang tải…' : 'Loading…'}</div>}
          {!loading && !list.length && <div className="empty" style={{ padding:24 }}><i className="bi bi-inbox"></i> {lang === 'vi' ? 'Không có email' : 'No emails'}</div>}
          {!loading && list.map(m => (
            <button key={m.id} className={'inbox-item' + (m.unread ? ' unread' : '') + (open && open.id === m.id ? ' sel' : '')} onClick={() => openMail(m)}>
              <Avatar name={m.fromName} size={30} />
              <div className="grow" style={{ minWidth:0 }}>
                <div className="flex items-center g8"><span className="ii-from truncate">{m.fromName}</span><span className="ii-date subtle mono">{fmtMailDate(m.date)}</span></div>
                <div className="ii-subj truncate">{m.unread && <i className="bi bi-circle-fill" style={{ fontSize:6, color:'var(--primary)', marginRight:5 }}></i>}{m.subject}{m.hasAttach && <i className="bi bi-paperclip subtle" style={{ marginLeft:5 }}></i>}</div>
                <div className="ii-snip truncate subtle">{m.snippet}</div>
              </div>
            </button>
          ))}
        </div>

        <div className="inbox-resizer" onPointerDown={startResize} title={lang === 'vi' ? 'Kéo để đổi độ rộng' : 'Drag to resize'}></div>

        <div className="card inbox-detail">
          {loadingMsg && <div className="empty" style={{ padding:40 }}><i className="bi bi-arrow-repeat spin"></i> {lang === 'vi' ? 'Đang tải email…' : 'Loading…'}</div>}
          {!loadingMsg && !open && <div className="empty" style={{ padding:40, textAlign:'center', height:'100%' }}><i className="bi bi-envelope-open" style={{ fontSize:32, opacity:.3 }}></i><div style={{ marginTop:8 }}>{lang === 'vi' ? 'Chọn một email để xem' : 'Select an email to read'}</div></div>}
          {!loadingMsg && open && (
            <div className="card-body col g14">
              <div className="flex justify-between items-start g8">
                <h2 style={{ fontSize:'var(--fs-xl)', margin:0 }}>{open.subject}</h2>
                <div className="flex g8 items-center" style={{ flex:'none' }}>
                  <button className="btn btn-subtle btn-sm" onClick={() => reply(open)}><i className="bi bi-reply"></i>{lang === 'vi' ? 'Trả lời' : 'Reply'}</button>
                  {(() => { const ra = replyAllTargets(open); return (ra.to.length + ra.cc.length) > 1 && (
                    <button className="btn btn-subtle btn-sm" onClick={() => replyAll(open)}><i className="bi bi-reply-all"></i>{lang === 'vi' ? 'Trả lời tất cả' : 'Reply all'}</button>
                  ); })()}
                </div>
              </div>
              <div className="flex g8 items-center">
                <Avatar name={open.fromName} size={40} />
                <div className="grow" style={{ minWidth:0 }}>
                  <div style={{ fontWeight:600 }}>{open.fromName}</div>
                  <div className="subtle mono truncate" style={{ fontSize:'var(--fs-sm)' }}>{open.from}</div>
                </div>
                <span className="subtle mono" style={{ fontSize:'var(--fs-sm)' }}>{fmtMailDate(open.date)}</span>
              </div>
              {open.attachments && open.attachments.length > 0 && (
                <div className="flex g8 wrap">{open.attachments.map((a, i) => (
                  <button key={i} className="badge badge-neutral attach-dl" onClick={() => downloadAttach(a)} disabled={dling === a.attachmentId} title={lang === 'vi' ? 'Tải xuống' : 'Download'}>
                    <i className={'bi ' + (dling === a.attachmentId ? 'bi-arrow-repeat spin' : 'bi-paperclip')}></i>{a.name}{a.size ? <span className="subtle"> ({a.size < 1048576 ? Math.round(a.size / 1024) + ' KB' : (a.size / 1048576).toFixed(1) + ' MB'})</span> : null}<i className="bi bi-download" style={{ marginLeft:2, opacity:.7 }}></i>
                  </button>
                ))}</div>
              )}
              <div className="menu-sep"></div>
              <div className="mail-html" dangerouslySetInnerHTML={{ __html: open.html || ('<pre style="white-space:pre-wrap;font-family:inherit">' + (open.text || open.snippet || '') + '</pre>') }} />
            </div>
          )}
        </div>
      </div>
    </div>
  );
}

// Định dạng ngày RFC2822 của Gmail → gọn (giờ nếu hôm nay, không thì dd/MM).
function fmtMailDate(s) {
  if (!s) return '';
  const d = new Date(s);
  if (isNaN(d)) return s;
  const dd = String(d.getDate()).padStart(2, '0'), mm = String(d.getMonth() + 1).padStart(2, '0');
  return dd + '/' + mm;
}

// Email "Đã gửi" hiển thị theo vai trò: admin/quản lý thấy tất cả; user thường chỉ thấy của mình
// (email mock/seed không có sentBy → mọi người đều thấy, giữ demo chạy được).
function canSeeAllMail(p){ return p.role === 'admin' || p.role === 'manager'; }
function visibleSent(p){ return canSeeAllMail(p) ? p.sentEmails : p.sentEmails.filter(e => !e.sentBy || e.sentBy === p.me.email); }

function MailSent() {
  const p = usePortal();
  const { t, lang } = useLang();
  const [open, setOpen] = React.useState(null);
  const seeAll = canSeeAllMail(p);
  const srt = useTableSort();
  const list = srt.sortRows(visibleSent(p),
    { to:e => (e.to || []).join(', '), subject:e => e.subject, sender:e => e.sentBy, status:e => e.status, date:e => e.date });
  return (
    <div className="page pagefade">
      <div className="page-head"><div><h1>{t('mail.sent')}</h1><div className="sub">{list.length} {lang === 'vi' ? 'email đã gửi' : 'emails sent'}{seeAll && <span className="badge badge-neutral" style={{ marginLeft:8 }}><i className="bi bi-people"></i>{lang === 'vi' ? 'Tất cả người dùng' : 'All users'}</span>}</div></div><button className="btn btn-primary" onClick={() => p.navigate({ name:'module', module:'mail', sub:'compose' })}><i className="bi bi-pencil-square"></i>{t('mail.compose')}</button></div>
      <div className="card"><div style={{ overflow:'auto' }}>
        <table className="tbl">
          <thead><tr><ThSort k="to" sort={srt}>{t('mail.to')}</ThSort><ThSort k="subject" sort={srt}>{t('mail.subject')}</ThSort>{seeAll && <ThSort k="sender" sort={srt}>{lang === 'vi' ? 'Người gửi' : 'Sender'}</ThSort>}<ThSort k="status" sort={srt}>{t('c.status')}</ThSort><ThSort k="date" sort={srt}>{lang === 'vi' ? 'Thời gian' : 'Sent'}</ThSort></tr></thead>
          <tbody>
            {list.map(e => (
              <tr key={e.id} className="mail-row" onClick={() => setOpen(e)}>
                <td><span className="flex g8 items-center"><Avatar name={e.to[0]} size={22} color="var(--gray-400)" /><span className="mono" style={{ fontSize:'var(--fs-base)' }}>{e.to[0]}{e.to.length > 1 && <span className="badge badge-neutral" style={{ marginLeft:4 }}>+{e.to.length - 1}</span>}</span></span></td>
                <td><span className="subj">{e.subject}</span></td>
                {seeAll && <td className="muted mono" style={{ fontSize:'var(--fs-sm)' }}>{e.sentBy || '—'}</td>}
                <td><span className="badge badge-success"><i className="dot"></i>{lang === 'vi' ? 'Đã gửi' : 'Sent'}</span></td>
                <td className="muted mono" style={{ fontSize:'var(--fs-base)' }}>{fmtDate(e.date)}</td>
              </tr>
            ))}
          </tbody>
        </table>
      </div></div>
      {open && (
        <Modal title={open.subject} width={620} onClose={() => setOpen(null)} footer={<button className="btn" onClick={() => setOpen(null)}>{t('c.close')}</button>}>
          <div className="col g8" style={{ marginBottom:12 }}>
            <div className="det-row"><span className="dk">{t('mail.from')}</span><span className="dv mono">{p.me.email}</span></div>
            <div className="det-row"><span className="dk">{t('mail.to')}</span><span className="dv mono">{open.to.join(', ')}</span></div>
            <div className="det-row"><span className="dk">{lang === 'vi' ? 'Thời gian' : 'Sent'}</span><span className="dv mono">{fmtDate(open.date)}</span></div>
          </div>
          <div className="mail-html" dangerouslySetInnerHTML={{ __html:open.html }} />
        </Modal>
      )}
    </div>
  );
}

function MailTemplates() {
  const p = usePortal();
  const { t, lang } = useLang();
  const toast = useToast();
  const canEdit = p.role === 'manager' || p.role === 'admin';
  const tpls = p.templates;
  const [edit, setEdit] = React.useState(null);
  const [isNew, setIsNew] = React.useState(false);
  const [del, setDel] = React.useState(null);
  const tplName = (tpl) => (tpl.name && (tpl.name[lang] || tpl.name.vi)) || '';
  const newTemplate = () => { setIsNew(true); setEdit({ name:{ vi:'', en:'' }, subject:'', html:'' }); };
  const openEdit = (tpl) => { setIsNew(false); setEdit({ ...tpl, name:{ ...tpl.name } }); };
  const setName = (v) => setEdit(e => ({ ...e, name:{ vi:v, en:v } }));
  const save = () => {
    if (!edit.name.vi.trim()) { toast(lang === 'vi' ? 'Chưa có tên mẫu' : 'Template name required', 'error'); return; }
    if (isNew) p.addTemplate(edit); else p.updateTemplate(edit);
    setEdit(null);
    toast(isNew ? (lang === 'vi' ? 'Đã tạo mẫu' : 'Template created') : (lang === 'vi' ? 'Đã lưu mẫu' : 'Template saved'), 'success');
  };
  return (
    <div className="page pagefade">
      <div className="page-head">
        <div><h1>{t('mail.templates')}</h1><div className="sub">{tpls.length} {lang === 'vi' ? 'mẫu email dùng nhanh.' : 'reusable templates.'} {!canEdit && <span className="badge badge-neutral">{lang === 'vi' ? 'Chỉ Quản lý/Admin được sửa' : 'Manager/Admin can edit'}</span>}</div></div>
        {canEdit && <button className="btn btn-primary" onClick={newTemplate}><i className="bi bi-plus-lg"></i>{lang === 'vi' ? 'Tạo mẫu' : 'New template'}</button>}
      </div>
      <div className="app-grid" style={{ gridTemplateColumns:'1fr 1fr' }}>
        {tpls.map(tpl => (
          <div key={tpl.id} className="card">
            <div className="card-head"><h3 style={{ fontSize:'var(--fs-md)' }}><i className="bi bi-envelope-paper" style={{ color:'var(--primary)', marginRight:6 }}></i>{tplName(tpl)}</h3>
              {canEdit && <div className="flex g4">
                <button className="btn btn-ghost btn-sm" onClick={() => openEdit(tpl)}><i className="bi bi-pencil"></i>{t('c.edit')}</button>
                <button className="btn btn-ghost btn-sm" onClick={() => setDel(tpl)} title={t('c.delete')} style={{ color:'var(--danger)' }}><i className="bi bi-trash"></i></button>
              </div>}</div>
            <div className="card-body">
              <div className="subtle mono" style={{ fontSize:'var(--fs-sm)', marginBottom:8 }}>{tpl.subject}</div>
              <div className="mail-html" style={{ maxHeight:120, overflow:'hidden', fontSize:'var(--fs-base)' }} dangerouslySetInnerHTML={{ __html:tpl.html }} />
            </div>
          </div>
        ))}
        {!tpls.length && <div className="empty" style={{ gridColumn:'1 / -1' }}><i className="bi bi-envelope-paper"></i>{lang === 'vi' ? 'Chưa có mẫu nào' : 'No templates yet'}</div>}
      </div>
      {edit && (
        <Modal title={isNew ? (lang === 'vi' ? 'Tạo mẫu email' : 'New template') : (t('c.edit') + ' — ' + tplName(edit))} width={620} onClose={() => setEdit(null)}
          footer={<><button className="btn" onClick={() => setEdit(null)}>{t('c.cancel')}</button><button className="btn btn-primary" onClick={save}>{isNew ? (lang === 'vi' ? 'Tạo' : 'Create') : t('c.save')}</button></>}>
          <div className="col g16">
            <Field label={lang === 'vi' ? 'Tên mẫu' : 'Template name'}><input className="input" autoFocus value={edit.name.vi} onChange={e => setName(e.target.value)} placeholder={lang === 'vi' ? 'VD: Thư mời họp' : 'e.g. Meeting invite'} /></Field>
            <Field label={t('mail.subject')}><input className="input" value={edit.subject} onChange={e => setEdit({ ...edit, subject:e.target.value })} placeholder={lang === 'vi' ? 'Tiêu đề email' : 'Subject'} /></Field>
            <Field label={lang === 'vi' ? 'Nội dung HTML' : 'HTML body'}><textarea className="textarea mono" rows={7} value={edit.html} onChange={e => setEdit({ ...edit, html:e.target.value })} style={{ fontSize:'var(--fs-base)' }} placeholder="<p>…</p>" /></Field>
          </div>
        </Modal>
      )}
      {del && (
        <Modal title={lang === 'vi' ? 'Xóa mẫu email' : 'Delete template'} width={420} onClose={() => setDel(null)}
          footer={<><button className="btn" onClick={() => setDel(null)}>{t('c.cancel')}</button><button className="btn btn-danger" onClick={() => { p.deleteTemplate(del.id); setDel(null); toast(lang === 'vi' ? 'Đã xóa mẫu' : 'Template deleted', 'success'); }}>{t('c.delete')}</button></>}>
          <p style={{ margin:0 }}>{lang === 'vi' ? 'Bạn có chắc muốn xóa mẫu' : 'Delete template'} <b>{tplName(del)}</b>?</p>
        </Modal>
      )}
    </div>
  );
}

function MailSettings() {
  const p = usePortal();
  const { t, lang } = useLang();
  const toast = useToast();
  const isAdmin = p.role === 'admin';
  const realSend = !!(window.GMail && GMail.configured());
  const [sig, setSig] = React.useState(p.mailSettings.signature);
  return (
    <div className="page pagefade">
      <div className="page-head"><div><h1>{t('c.settings')}</h1><div className="sub">{lang === 'vi' ? 'Kết nối & chữ ký mặc định.' : 'Connection & default signature.'}</div></div></div>
      {!isAdmin && <div className="card" style={{ marginBottom:14 }}><div className="card-body flex g8 items-center"><i className="bi bi-info-circle" style={{ color:'var(--info)' }}></i>{lang === 'vi' ? 'Chỉ Admin có thể chỉnh kết nối hệ thống.' : 'Only Admin can change the system connection.'}</div></div>}
      <div className="card" style={{ maxWidth:620 }}>
        <div className="card-head"><h3>{lang === 'vi' ? 'Kết nối Gmail' : 'Gmail connection'}</h3>
          {realSend ? <span className="badge badge-success"><i className="dot"></i>{lang === 'vi' ? 'Gửi thật (Gmail API)' : 'Live (Gmail API)'}</span>
            : <span className="badge badge-warning"><i className="dot"></i>{lang === 'vi' ? 'Mô phỏng' : 'Mock'}</span>}
        </div>
        <div className="card-body col g16">
          <div className="det-row"><span className="dk">{lang === 'vi' ? 'Chế độ gửi' : 'Send mode'}</span><span className="dv">{realSend ? (lang === 'vi' ? 'Gửi thật qua tài khoản Google đang đăng nhập' : 'Real send via signed-in Google account') : (lang === 'vi' ? 'Mô phỏng (ghi vào danh sách Đã gửi)' : 'Mock (records to Sent list)')}</span></div>
          <div className="det-row"><span className="dk">{lang === 'vi' ? 'Tài khoản gửi' : 'Sending account'}</span><span className="dv mono">{realSend ? p.me.email : p.mailSettings.account}</span></div>
          {!realSend && <div className="subtle" style={{ fontSize:'var(--fs-base)' }}><i className="bi bi-info-circle"></i> {lang === 'vi' ? 'Bật gửi thật: điền GOOGLE_OAUTH_CLIENT_ID ở config.jsx + cấu hình Google Cloud (docs/gmail-send.md).' : 'Enable live sending: set GOOGLE_OAUTH_CLIENT_ID in config.jsx + Google Cloud setup (docs/gmail-send.md).'}</div>}
          <Field label={lang === 'vi' ? 'Chữ ký HTML mặc định' : 'Default HTML signature'}>
            <textarea className="textarea mono" rows={4} value={sig} onChange={e => setSig(e.target.value)} disabled={!isAdmin} style={{ fontSize:'var(--fs-base)', background:isAdmin ? 'var(--bg)' : 'var(--bg-sunken)' }} />
          </Field>
          <div className="mail-html" dangerouslySetInnerHTML={{ __html:sig }} />
          {isAdmin && <div className="flex justify-end"><button className="btn btn-primary" onClick={() => { p.saveMailSettings({ signature:sig }); toast(lang === 'vi' ? 'Đã lưu cài đặt' : 'Settings saved'); }}>{t('c.save')}</button></div>}
        </div>
      </div>
      <div className="card" style={{ maxWidth:620, marginTop:14 }}>
        <div className="card-head"><h3><i className="bi bi-qr-code" style={{ marginRight:6 }}></i>{lang === 'vi' ? 'Chữ ký namecard (cá nhân)' : 'Namecard signature (personal)'}</h3><span className="badge badge-info">vCard QR</span></div>
        <div className="card-body col g12">
          <div className="subtle" style={{ fontSize:'var(--fs-sm)' }}>{lang === 'vi' ? 'Chữ ký namecard riêng của bạn (có QR vCard). Khi soạn email bấm "Chèn chữ ký namecard"; chỉnh sửa trong Hồ sơ.' : 'Your personal namecard signature (vCard QR). Use "Insert namecard" when composing; edit in your profile.'}</div>
          <SignatureCard card={loadNamecard(p.me, p.branding)} branding={p.branding} />
          <div className="flex justify-end"><button className="btn btn-sm btn-primary" onClick={() => p.navigate({ name:'settings' })}><i className="bi bi-pencil-square"></i>{lang === 'vi' ? 'Quản lý trong Hồ sơ' : 'Manage in profile'}</button></div>
        </div>
      </div>
    </div>
  );
}

function MailModule() {
  const p = usePortal();
  const { t, lang } = useLang();
  const sub = p.route.sub || 'inbox';
  const items = [
    { id:'inbox', icon:'bi-inbox', label:lang === 'vi' ? 'Hộp thư đến' : 'Inbox' },
    { id:'compose', icon:'bi-pencil-square', label:t('mail.compose') },
    { id:'sent', icon:'bi-send', label:t('mail.sent'), count:visibleSent(p).length },
    { id:'templates', icon:'bi-file-earmark-richtext', label:t('mail.templates') },
    { id:'settings', icon:'bi-gear', label:t('c.settings') },
  ];
  const go = (id) => p.navigate({ name:'module', module:'mail', sub:id });
  return (<>
    <ModuleSidebar app={MAIL_APP} items={items} active={sub} onNavigate={go} />
    <main className="main">
      {sub === 'inbox' && <MailInbox />}
      {sub === 'compose' && <MailCompose />}
      {sub === 'sent' && <MailSent />}
      {sub === 'templates' && <MailTemplates />}
      {sub === 'help' && <ModuleHelp moduleId="mail" app={MAIL_APP} />}
      {sub === 'settings' && <MailSettings />}
    </main>
  </>);
}

/* Dashboard widget */
function EmailWidget() {
  const p = usePortal();
  const { t, lang } = useLang();
  const seeAll = canSeeAllMail(p);
  const list = visibleSent(p);
  return (
    <WidgetShell wid="mail" icon="bi-envelope" iconColor="var(--primary)"
      title={<React.Fragment>{t('mail.sent')}{seeAll && <span className="badge badge-neutral" style={{ marginLeft:6 }}>{lang === 'vi' ? 'Tất cả' : 'All'}</span>}</React.Fragment>}
      onViewAll={() => p.openApp(MAIL_APP)} onNew={() => p.quick('mail')} newLabel={t('mail.compose')} newIcon="bi-pencil-square">
        <div className="flex g16" style={{ marginBottom:8 }}>
          <div><div className="k-val" style={{ fontSize:'var(--fs-2xl)', fontWeight:700 }}>{list.length}</div><div className="subtle" style={{ fontSize:'var(--fs-sm)' }}>{lang === 'vi' ? 'đã gửi' : 'sent'}</div></div>
        </div>
        {list.slice(0, 3).map(e => (
          <div key={e.id} className="list-row"><i className="bi bi-envelope-check" style={{ color:'var(--success)' }}></i><span className="grow truncate">{e.subject}</span><span className="subtle mono" style={{ fontSize:'var(--fs-sm)' }}>{e.date.slice(5, 10)}</span></div>
        ))}
    </WidgetShell>
  );
}

Object.assign(window, { MailModule, EmailWidget, RichEditor });
