// /public/assets/Campaigns.jsx
function CampaignsPage() {
  const { AppBootstrap } = window.__CRM__;
  const {
    Container, Paper, Typography, TextField, Button, Table, TableHead, TableRow, TableCell, TableBody,
    IconButton, Stack, Pagination, TableContainer, useMediaQuery, Card, CardContent, Divider,
    Dialog, DialogTitle, DialogContent, DialogActions, MenuItem, Chip, Tooltip, Grid, InputAdornment,
    Snackbar, Alert, Switch, FormControlLabel, Tabs, Tab, Box
  } = MaterialUI;

  const isXs = useMediaQuery('(max-width:600px)');
  const isSm = useMediaQuery('(max-width:900px)');

  const [q, setQ] = React.useState("");
  const [rows, setRows] = React.useState([]);
  const [total, setTotal] = React.useState(0);
  const [page, setPage] = React.useState(1);
  const limit = 25;

  const [openModal, setOpenModal] = React.useState(false);
  const [mode, setMode] = React.useState('create'); // create|edit|view
  const [locked, setLocked] = React.useState(false);
  const [lists, setLists] = React.useState([]);
  const [inboxes, setInboxes] = React.useState([]);
  const [inboxesLoading, setInboxesLoading] = React.useState(false);

  const emptyForm = {
    id: null,
    name: "",
    list_id: "",
    inbox_id: "",
    typemsg: "Phone", // novo campo
    tags: "",
    schedule: "",
    msgs: ["","","","",""],
    imgs: [null,null,null,null,null],
    imgUrls: [null,null,null,null,null],
    use_html: 0,
  };
  const [form, setForm] = React.useState(emptyForm);
  const [focusMsgIdx, setFocusMsgIdx] = React.useState(null);
  const [tab, setTab] = React.useState(0);

  // HTML editor
  const [useHtml, setUseHtml] = React.useState(false);
  const [quillReady, setQuillReady] = React.useState(false);
  const quillRefs = React.useRef([null,null,null,null,null]);

  // toast
  const [toast, setToast] = React.useState({ open:false, msg:'', sev:'info' });
  const notify = (msg, sev='info') => setToast({ open:true, msg, sev });

  const VARS = ["{name}","{number}","{email}","{city}","{state}","{zip}","{country}"];

  function statusChip(s) {
    const map = { Draft:'default', Scheduled:'info', Running:'success', Paused:'warning', Stopped:'error', Completed:'success', Failed:'error' };
    return <Chip size="small" label={s} color={map[s] || 'default'} />;
  }

  async function load(p=1) {
    const offset = (p-1)*limit;
    const r = await fetch(`/api/campaigns_list.php?q=${encodeURIComponent(q)}&limit=${limit}&offset=${offset}`, { credentials:'include' });
    const j = await r.json();
    setRows(j.items||[]); setTotal(j.total||0); setPage(p);
  }
  React.useEffect(()=>{ load(1); }, []);

  async function loadLists() {
    const r = await fetch(`/api/lists_list.php?limit=200&offset=0`, { credentials:'include' });
    const j = await r.json(); setLists(j.items||[]);
  }
  async function loadInboxes() {
    setInboxesLoading(true);
    try {
      const r = await fetch('/api/settings_chatwoot_inboxes.php', { credentials:'include' });
      const j = await r.json();
      setInboxes(j.ok ? (j.items||[]) : []);
    } finally {
      setInboxesLoading(false);
    }
  }
  async function loadDefaultInbox() {
    const r = await fetch('/api/settings_chatwoot_get.php',{credentials:'include'});
    const j = await r.json();
    const defId = j?.config?.default_inbox_id ? String(j.config.default_inbox_id) : '';
    if (defId) setForm(f => ({ ...f, inbox_id: defId }));
  }

  function openCreate() {
    setMode('create'); setLocked(false);
    setForm(structuredClone(emptyForm));
    setUseHtml(false);
    setTab(0);
    setOpenModal(true);
    loadLists();
    loadInboxes().then(loadDefaultInbox);
    setTimeout(()=>setFocusMsgIdx(0),0);
  }

  function toInputScheduleLocal(iso) {
    if (!iso) return "";
    const [d, t=""] = iso.split(" ");
    const hm = t.slice(0,5);
    return `${d}T${hm}`;
  }

  async function openEdit(id) {
    const r = await fetch(`/api/campaigns_get.php?id=${id}`, { credentials:'include' });
    if(!r.ok){ notify('Campaign not found.','error'); return; }
    const { campaign:c } = await r.json();
    const editable = (c.status==='Draft' || c.status==='Scheduled');
    setMode(editable ? 'edit' : 'view');
    setLocked(!editable);
    setUseHtml(c.use_html === 1);
    setForm({
      id: c.id,
      name: c.name || "",
      list_id: String(c.list_id || ""),
      inbox_id: String(c.inbox_id || ""),
      typemsg: c.typemsg || (c.use_html === 1 ? 'Email' : 'Phone'),
      tags: c.tags || "",
      schedule: c.scheduled_at ? toInputScheduleLocal(c.scheduled_at) : "",
      msgs: [c.msg1||"", c.msg2||"", c.msg3||"", c.msg4||"", c.msg5||""],
      imgs: [null,null,null,null,null],
      imgUrls: [c.img1||null,c.img2||null,c.img3||null,c.img4||null,c.img5||null],
      use_html: c.use_html || 0,
    });
    setOpenModal(true);
    setTab(0);
    setTimeout(()=>setFocusMsgIdx(0),0);
    loadLists();
    await loadInboxes();
  }

  function canEdit(status){ return status==='Draft' || status==='Scheduled'; }
  function onAnalytics(id){ location.hash = `#/campaigns/${id}/analytics`; }

  async function onDelete(id, status){
    if(!canEdit(status)) return;
    if(!confirm('Delete this campaign?')) return;
    const fd = new FormData(); fd.append('id', String(id));
    const r = await fetch('/api/campaigns_delete.php', { method:'POST', body:fd, credentials:'include' });
    if(!r.ok){ notify('Delete blocked.','warning'); return; }
    notify('Campaign deleted.','success');
    load(1);
  }

  async function player(id, action, status){
    const fd = new FormData(); fd.append('id', String(id)); fd.append('action', action);
    const r = await fetch('/api/campaigns_action.php', { method:'POST', body:fd, credentials:'include' });
    if(!r.ok){
      notify('Action not allowed. Check settings, inbox or status.','warning');
      return;
    }
    if (action==='play') {
      notify(status==='Paused' ? 'Resumed' : 'Started','success');
    } else if (action==='pause') {
      notify('Paused','success');
    } else {
      notify('Stopped','success');
    }
    load(page);
  }

  // ==== Quill loader ====
  function loadOnce(id, hrefOrSrc, isCss=false) {
    return new Promise((resolve, reject)=>{
      if (document.getElementById(id)) return resolve();
      const el = isCss ? document.createElement('link') : document.createElement('script');
      if (isCss) { el.rel='stylesheet'; el.href=hrefOrSrc; }
      else { el.src=hrefOrSrc; el.async=true; }
      el.id = id;
      el.onload = ()=>resolve();
      el.onerror = ()=>reject(new Error('load_fail '+hrefOrSrc));
      (isCss ? document.head : document.body).appendChild(el);
    });
  }
  async function ensureQuill() {
    if (window.ReactQuill && window.Quill) { setQuillReady(true); return; }
    try {
      await loadOnce('quill-css', 'https://cdn.jsdelivr.net/npm/quill@1.3.7/dist/quill.snow.css', true);
      await loadOnce('quill-js',  'https://cdn.jsdelivr.net/npm/quill@1.3.7/dist/quill.min.js');
      await loadOnce('react-quill-umd', 'https://cdn.jsdelivr.net/npm/react-quill@2.0.0/dist/react-quill.min.js');
      setQuillReady(true);
    } catch(e) {
      notify('Failed to load HTML editor.','error');
      setUseHtml(false);
    }
  }
  React.useEffect(()=>{
    if (openModal && useHtml) ensureQuill();
  }, [openModal, useHtml]);

  // Altura mínima consistente do Quill
  React.useEffect(()=>{
    const s = document.createElement('style');
    s.id = 'quill-minheight';
    s.textContent = `
      .ql-container { min-height: 300px; }
      .ql-editor { min-height: 300px; }
    `;
    document.head.appendChild(s);
    return ()=>{ const el=document.getElementById('quill-minheight'); if(el) el.remove(); };
  },[]);

  // inserir variável
  function insertVar(v) {
    const targetIdx = (focusMsgIdx ?? tab);

    if (useHtml && quillReady) {
      const rq = quillRefs.current[targetIdx];
      const editor = rq && rq.getEditor ? rq.getEditor() : null;
      if (editor) {
        const sel = editor.getSelection(true);
        const index = sel ? sel.index : editor.getLength();
        editor.insertText(index, v);
        editor.setSelection(index + v.length, 0);
        return;
      }
    }

    const m = [...form.msgs];
    const el = document.getElementById(`msg-${targetIdx}`);
    if (el && typeof el.selectionStart === 'number') {
      const s = el.selectionStart, e = el.selectionEnd;
      const txt = m[targetIdx] || "";
      m[targetIdx] = txt.slice(0,s) + v + txt.slice(e);
      setForm({ ...form, msgs:m });
      setTimeout(()=>{ el.focus(); const pos=s+v.length; el.setSelectionRange?.(pos,pos); },0);
      return;
    }
    m[targetIdx] = (m[targetIdx]||"") + v;
    setForm({ ...form, msgs:m });
  }

  // preview local + manter file
  function onSelectFile(slot, file) {
    const imgs = [...form.imgs]; imgs[slot-1] = file || null;
    if (!file) { setForm({ ...form, imgs }); return; }
    const reader = new FileReader();
    reader.onload = e => {
      const urls = [...form.imgUrls];
      urls[slot-1] = e.target.result;
      setForm({ ...form, imgs, imgUrls: urls });
    };
    reader.readAsDataURL(file);
  }

  async function handleCreate() {
    if(!form.name.trim() || !form.list_id || !form.inbox_id){
      notify('Name, Contact list and Inbox are required.', 'warning'); return;
    }
    const fd = new FormData();
    fd.append('name', form.name.trim());
    fd.append('list_id', String(form.list_id));
    fd.append('inbox_id', String(form.inbox_id));
    const inboxName = inboxes.find(i=> String(i.id)===String(form.inbox_id))?.name || '';
    fd.append('inbox_name', inboxName);
    fd.append('typemsg', form.typemsg || 'Phone'); // novo
    fd.append('tags', form.tags.trim());
    fd.append('schedule', form.schedule.trim());
    fd.append('use_html', form.use_html ? '1' : '0');

    const r = await fetch('/api/campaigns_create.php', { method:'POST', body:fd, credentials:'include' });
    let j; try { j = await r.json(); } catch { notify('Create failed (invalid response).','error'); return; }
    if (!r.ok || !j?.ok) { notify('Failed to create campaign.','error'); return; }
    const newId = j.id;

    for (let slot=1; slot<=5; slot++){
      const f = form.imgs[slot-1];
      if (!f) continue;
      const ufd = new FormData();
      ufd.append('id', String(newId));
      ufd.append('slot', String(slot));
      ufd.append('file', f);
      const ur = await fetch('/api/campaigns_upload_image.php', { method:'POST', body:ufd, credentials:'include' });
      if (!ur.ok) notify(`Image ${slot} upload failed.`, 'warning');
    }

    const ufd2 = new FormData();
    ufd2.append('id', String(newId));
    for (let i=1;i<=5;i++) ufd2.append(`msg${i}`, form.msgs[i-1] || '');
    const sr = await fetch('/api/campaigns_update.php', { method:'POST', body: ufd2, credentials:'include' });
    if (!sr.ok) notify('Saved, but messages failed. Edit to retry.', 'warning');

    setOpenModal(false);
    notify('Campaign created.','success');
    load(1);
  }

  async function handleSaveEdit() {
    if (!form.id) return;
    const cr = await fetch(`/api/campaigns_get.php?id=${form.id}`, { credentials:'include' });
    if (!cr.ok) { notify('Campaign not found.','error'); return; }
    const { campaign:c } = await cr.json();
    if (!c || c.status !== 'Draft') {
      notify('Only Draft campaigns can be updated.','warning');
      setLocked(true);
      return;
    }

    for (let slot=1; slot<=5; slot++){
      const f = form.imgs[slot-1];
      if (!f) continue;
      const ufd = new FormData();
      ufd.append('id', String(form.id));
      ufd.append('slot', String(slot));
      ufd.append('file', f);
      const rr = await fetch('/api/campaigns_upload_image.php', { method:'POST', body:ufd, credentials:'include' });
      if (!rr.ok) notify(`Image ${slot} upload failed.`, 'warning');
    }

    const fd = new FormData();
    fd.append('id', String(form.id));
    fd.append('name', form.name.trim());
    fd.append('tags', form.tags.trim());
    fd.append('schedule', form.schedule.trim());
    fd.append('use_html', form.use_html ? '1' : '0');
    fd.append('typemsg', form.typemsg || 'Phone'); // novo
    if (form.inbox_id) {
      fd.append('inbox_id', String(form.inbox_id));
      const inboxName = inboxes.find(i=> String(i.id)===String(form.inbox_id))?.name || '';
      fd.append('inbox_name', inboxName);
    }
    for (let i=1;i<=5;i++) fd.append(`msg${i}`, form.msgs[i-1] || '');

    const r = await fetch('/api/campaigns_update.php', { method:'POST', body:fd, credentials:'include' });
    if (!r.ok) { notify('Save failed.','error'); return; }

    setOpenModal(false);
    notify('Campaign updated.','success');
    load(page);
  }

  const selectedInboxMissing = openModal && form.inbox_id && !inboxes.some(i=>String(i.id)===String(form.inbox_id));
  const pages = Math.max(1, Math.ceil(total/limit));

  const quillModules = React.useMemo(()=>({
    toolbar: [
      [{ header: [1,2,false] }],
      ['bold','italic','underline','strike'],
      [{ 'list': 'ordered' }, { 'list': 'bullet' }],
      ['link','blockquote','code-block','clean','image']
    ]
  }),[]);

  const CardRow = ({ r }) => (
    <Card variant="outlined" sx={{ mb:1, borderRadius:2 }}>
      <CardContent sx={{ p:2 }}>
        <Stack direction="row" justifyContent="space-between" alignItems="center">
          <Stack spacing={0.25}>
            <Typography variant="subtitle1" sx={{ fontWeight:700, overflow:'hidden', textOverflow:'ellipsis', whiteSpace:'nowrap' }}>{r.name}</Typography>
            <Typography variant="body2" color="text.secondary" sx={{ overflow:'hidden', textOverflow:'ellipsis', whiteSpace:'nowrap' }}>
              {r.list_name} • Inbox: {r.inbox_name || '-'} • Tipo: {r.typemsg || '-'}
            </Typography>
          </Stack>
          {statusChip(r.status)}
        </Stack>
        <Divider sx={{ my:1 }} />
        <Stack direction="row" spacing={1} justifyContent="flex-end">
          {r.status==='Running' ? (
            <Tooltip title="Pause">
              <IconButton size="small" onClick={()=>player(r.id,'pause',r.status)}>
                <span className="material-icons">pause</span>
              </IconButton>
            </Tooltip>
          ) : (
            <Tooltip title="Play">
              <span>
                <IconButton size="small" onClick={()=>player(r.id,'play',r.status)} disabled={!(r.status==='Draft'||r.status==='Scheduled'||r.status==='Paused')}>
                  <span className="material-icons">play_arrow</span>
                </IconButton>
              </span>
            </Tooltip>
          )}
          <Tooltip title="Stop">
            <span>
              <IconButton size="small" onClick={()=>player(r.id,'stop',r.status)} disabled={!(r.status==='Running'||r.status==='Paused')}>
                <span className="material-icons">stop</span>
              </IconButton>
            </span>
          </Tooltip>
          <Tooltip title="Analytics">
            <IconButton size="small" onClick={()=>onAnalytics(r.id)}>
              <span className="material-icons">analytics</span>
            </IconButton>
          </Tooltip>
          <Tooltip title={canEdit(r.status) ? "Edit" : "View"}>
            <IconButton size="small" onClick={()=>openEdit(r.id)}>
              <span className="material-icons">edit</span>
            </IconButton>
          </Tooltip>
          <Tooltip title="Delete">
            <span>
              <IconButton size="small" onClick={()=>onDelete(r.id,r.status)} disabled={!canEdit(r.status)}>
                <span className="material-icons">delete</span>
              </IconButton>
            </span>
          </Tooltip>
        </Stack>
        <Stack direction="row" spacing={2} sx={{ mt:1 }} color="text.secondary">
          <Typography variant="caption">Schedule: {r.scheduled_at || '-'}</Typography>
          <Typography variant="caption">Completed: {r.completed_at ? 'Yes' : 'No'}</Typography>
        </Stack>
      </CardContent>
    </Card>
  );

  const ReactQuillComp = (window && window.ReactQuill) ? window.ReactQuill : null;

  return (
    <AppBootstrap>
      <Container maxWidth="xl" sx={{ py:3 }}>
        <Stack direction={{ xs:'column', md:'row' }} spacing={2} alignItems={{ xs:'stretch', md:'center' }} justifyContent="space-between" sx={{ mb:2 }}>
          <Typography variant="h5" sx={{ fontWeight:700 }}>Campaigns</Typography>
          <Stack direction="row" spacing={1} flexWrap="wrap">
            <TextField size="small" placeholder="Search by campaign name" value={q} onChange={e=>setQ(e.target.value)} />
            <Button variant="outlined" onClick={()=>load(1)}>Search</Button>
            <Button variant="contained" onClick={openCreate}>New Campaign</Button>
          </Stack>
        </Stack>

        {isXs ? (
          <div>
            {rows.length===0 ? <Typography sx={{ p:2 }} color="text.secondary">No campaigns.</Typography>
              : rows.map(r => <CardRow key={r.id} r={r} />)}
          </div>
        ) : (
          <Paper>
            <TableContainer sx={{ maxHeight: isSm ? 520 : 'none' }}>
              <Table size="small" stickyHeader>
                <TableHead>
                  <TableRow>
                    <TableCell>Name</TableCell>
                    <TableCell>Status</TableCell>
                    <TableCell>Contact List</TableCell>
                    <TableCell>Inbox</TableCell>
                    <TableCell>Tipo</TableCell>{/* novo */}
                    <TableCell>Schedule</TableCell>
                    <TableCell>Completed</TableCell>
                    <TableCell align="right">Actions</TableCell>
                  </TableRow>
                </TableHead>
                <TableBody>
                  {rows.map(r=>(
                    <TableRow key={r.id} hover>
                      <TableCell sx={{ maxWidth:260, whiteSpace:'nowrap', overflow:'hidden', textOverflow:'ellipsis' }}>{r.name}</TableCell>
                      <TableCell>{statusChip(r.status)}</TableCell>
                      <TableCell sx={{ maxWidth:220, whiteSpace:'nowrap', overflow:'hidden', textOverflow:'ellipsis' }}>{r.list_name}</TableCell>
                      <TableCell sx={{ maxWidth:220, whiteSpace:'nowrap', overflow:'hidden', textOverflow:'ellipsis' }}>{r.inbox_name || '-'}</TableCell>
                      <TableCell>{r.typemsg || '-'}</TableCell>{/* novo */}
                      <TableCell>{r.scheduled_at || '-'}</TableCell>
                      <TableCell>{r.completed_at ? 'Yes' : 'No'}</TableCell>
                      <TableCell align="right">
                        <Stack direction="row" spacing={1} justifyContent="flex-end">
                          {r.status==='Running' ? (
                            <Tooltip title="Pause">
                              <IconButton size="small" onClick={()=>player(r.id,'pause',r.status)}>
                                <span className="material-icons">pause</span>
                              </IconButton>
                            </Tooltip>
                          ) : (
                            <Tooltip title="Play">
                              <span>
                                <IconButton size="small" onClick={()=>player(r.id,'play',r.status)} disabled={!(r.status==='Draft'||r.status==='Scheduled'||r.status==='Paused')}>
                                  <span className="material-icons">play_arrow</span>
                                </IconButton>
                              </span>
                            </Tooltip>
                          )}
                          <Tooltip title="Stop">
                            <span>
                              <IconButton size="small" onClick={()=>player(r.id,'stop',r.status)} disabled={!(r.status==='Running'||r.status==='Paused')}>
                                <span className="material-icons">stop</span>
                              </IconButton>
                            </span>
                          </Tooltip>
                          <Tooltip title="Analytics">
                            <IconButton size="small" onClick={()=>onAnalytics(r.id)}>
                              <span className="material-icons">analytics</span>
                            </IconButton>
                          </Tooltip>
                          <Tooltip title={canEdit(r.status) ? "Edit" : "View"}>
                            <IconButton size="small" onClick={()=>openEdit(r.id)}>
                              <span className="material-icons">edit</span>
                            </IconButton>
                          </Tooltip>
                          <Tooltip title="Delete">
                            <span>
                              <IconButton size="small" onClick={()=>onDelete(r.id,r.status)} disabled={!canEdit(r.status)}>
                                <span className="material-icons">delete</span>
                              </IconButton>
                            </span>
                          </Tooltip>
                        </Stack>
                      </TableCell>
                    </TableRow>
                  ))}
                  {rows.length===0 && (
                    <TableRow><TableCell colSpan={8}><Typography sx={{ p:2 }} color="text.secondary">No campaigns.</Typography></TableCell></TableRow>
                  )}
                </TableBody>
              </Table>
            </TableContainer>
          </Paper>
        )}

        <Stack alignItems="center" sx={{ mt:2 }}>
          <Pagination count={pages} page={page} onChange={(_,p)=>load(p)} />
        </Stack>
      </Container>

      <Dialog
        open={openModal}
        onClose={()=>setOpenModal(false)}
        maxWidth="md"
        fullWidth
        keepMounted
        disableRestoreFocus
      >
        <DialogTitle>{mode==='create' ? 'New Campaign' : (locked ? 'View Campaign' : 'Edit Campaign')}</DialogTitle>
        <DialogContent dividers>
          <Stack spacing={2}>
            <Grid container spacing={2}>
              <Grid item xs={12} md={6}>
                <TextField label="Campaign name" value={form.name} onChange={e=>setForm({...form,name:e.target.value})} fullWidth required disabled={locked} />
              </Grid>
              <Grid item xs={12} md={6}>
                <TextField select label="Contact list" value={form.list_id} onChange={e=>setForm({...form,list_id:e.target.value})} fullWidth required disabled={locked}>
                  {lists.map(l => <MenuItem key={l.id} value={l.id}>{l.name} ({l.total_contacts||0})</MenuItem>)}
                </TextField>
              </Grid>
              <Grid item xs={12} md={6}>
                <TextField
                  select
                  label="Chatwoot inbox"
                  value={form.inbox_id}
                  onChange={e=>setForm({...form,inbox_id:e.target.value})}
                  fullWidth
                  required
                  disabled={locked || inboxesLoading}
                  helperText={inboxesLoading ? 'Loading inboxes…' : ''}
                >
                  {selectedInboxMissing && (
                    <MenuItem value={form.inbox_id}>Selected inbox (loading…)</MenuItem>
                  )}
                  {inboxes.map(i => (
                    <MenuItem key={i.id} value={String(i.id)}>
                      {i.name} ({i.channel||'channel'})
                    </MenuItem>
                  ))}
                </TextField>
              </Grid>
              <Grid item xs={12} md={6}>
                <TextField
                  select
                  label="Type"
                  value={form.typemsg}
                  onChange={e=>setForm({...form, typemsg:e.target.value})}
                  fullWidth
                  required
                  disabled={locked}
                  helperText="Seleciona coluna do contato a usar"
                >
                  <MenuItem value="Phone">Phone</MenuItem>
                  <MenuItem value="Email">Email</MenuItem>
                </TextField>
              </Grid>
              <Grid item xs={12} md={6}>
                <TextField label="Tags (comma separated)" value={form.tags} onChange={e=>setForm({...form,tags:e.target.value})} fullWidth disabled={locked} />
              </Grid>
              <Grid item xs={12} md={6}>
                <TextField
                  label="Schedule"
                  type="datetime-local"
                  value={form.schedule}
                  onChange={(e)=>setForm({...form, schedule: e.target.value})}
                  fullWidth
                  InputLabelProps={{ shrink: true }}
                  disabled={locked}
                  InputProps={{ endAdornment:<InputAdornment position="end"><span className="material-icons" style={{fontSize:18,opacity:.7}}>schedule</span></InputAdornment> }}
                />
              </Grid>
            </Grid>

            <Stack direction="row" spacing={1} alignItems="center" sx={{ mt:1 }}>
              <FormControlLabel
                control={
                  <Switch
                    checked={useHtml}
                    onChange={(e)=>{
                      const v = e.target.checked;
                      setUseHtml(v);
                      setForm(f=>({
                        ...f,
                        use_html: v ? 1 : 0,
                        typemsg: v ? 'Email' : (f.typemsg === 'Email' ? 'Phone' : f.typemsg)
                      }));
                    }}
                    disabled={locked}
                  />
                }
                label="Use HTML editor for messages (email)"
              />
              {useHtml && !quillReady && <Typography variant="body2" color="text.secondary">Loading editor…</Typography>}
            </Stack>

            <Stack direction="row" spacing={1} flexWrap="wrap" sx={{ mt:1 }}>
              {VARS.map(v => (
                <Chip key={v} size="small" label={v} onClick={()=>insertVar(v)} />
              ))}
            </Stack>

            <Tabs value={tab} onChange={(_,v)=>{ setTab(v); setFocusMsgIdx(v); }} variant="scrollable" scrollButtons="auto" sx={{ mt:2 }}>
              {[0,1,2,3,4].map(idx=>(<Tab key={idx} label={`Message ${idx+1}`} />))}
            </Tabs>

            {[0,1,2,3,4].map(idx=>(
              <Box key={idx} role="tabpanel" hidden={tab!==idx} sx={{mt:2, width:'100%'}}>
                <Paper variant="outlined" sx={{ p:2 }}>
                  {/* STACK VERTICAL: upload em cima, editor abaixo */}
                  <Stack spacing={1}>
                    <div>
                      <Button variant="outlined" component="label" disabled={locked}>
                        {form.imgs[idx]?.name ? `Selected: ${form.imgs[idx].name}` : (form.imgUrls[idx] ? 'Replace image' : 'Upload image')}
                        <input type="file" accept="image/*" hidden onChange={(e)=>{ onSelectFile(idx+1, e.target.files?.[0] || null); }} />
                      </Button>
                      {form.imgUrls[idx] && (
                        <div style={{marginTop:8}}>
                          <img src={form.imgUrls[idx]} alt={`img${idx+1}`} style={{maxWidth:'100%',borderRadius:8}}/>
                        </div>
                      )}
                    </div>

                    {!useHtml ? (
                      <TextField
                        id={`msg-${idx}`}
                        label={`Message ${idx+1}`}
                        value={form.msgs[idx]}
                        onChange={e=>{ const m=[...form.msgs]; m[idx]=e.target.value; setForm({...form,msgs:m}); }}
                        onFocus={()=>setFocusMsgIdx(idx)}
                        onBlur={()=>setFocusMsgIdx(null)}
                        fullWidth multiline minRows={8} disabled={locked}
                        helperText={`${(form.msgs[idx]||'').length} chars`}
                        sx={{ width:'100%' }}
                      />
                    ) : (
                      (useHtml && quillReady && window.ReactQuill) ? (
                        <div onFocus={()=>setFocusMsgIdx(idx)} onBlur={()=>setFocusMsgIdx(null)} style={{ width:'100%' }}>
                          <window.ReactQuill
                            ref={(el)=>{ quillRefs.current[idx]=el; }}
                            theme="snow"
                            value={form.msgs[idx]}
                            onChange={(val)=>{ const m=[...form.msgs]; m[idx]=val; setForm({...form, msgs:m}); }}
                            modules={quillModules}
                            readOnly={locked}
                            style={{ minHeight:300, width:'100%' }}
                          />
                        </div>
                      ) : (
                        <TextField
                          label={`Message ${idx+1}`}
                          value={form.msgs[idx]}
                          onChange={e=>{ const m=[...form.msgs]; m[idx]=e.target.value; setForm({...form,msgs:m}); }}
                          fullWidth multiline minRows={8} disabled
                          helperText="Editor loading…"
                        />
                      )
                    )}
                  </Stack>
                </Paper>
              </Box>
            ))}
          </Stack>
        </DialogContent>
        <DialogActions>
          <Button onClick={()=>setOpenModal(false)}>Close</Button>
          {mode==='create' && <Button variant="contained" onClick={handleCreate} disabled={locked || !form.name.trim() || !form.list_id || !form.inbox_id}>Create</Button>}
          {mode==='edit'   && <Button variant="contained" onClick={handleSaveEdit} disabled={locked || !form.id}>Save</Button>}
        </DialogActions>
      </Dialog>

      <Snackbar
        open={toast.open}
        autoHideDuration={3000}
        onClose={()=>setToast({...toast, open:false})}
        anchorOrigin={{ vertical:'bottom', horizontal:'right' }}
      >
        <Alert onClose={()=>setToast({...toast, open:false})} severity={toast.sev} variant="filled" sx={{ width: '100%' }}>
          {toast.msg}
        </Alert>
      </Snackbar>
    </AppBootstrap>
  );
}
window.CampaignsPage = CampaignsPage;
