// Peças comuns do console de gestão.
const DSc = window.WiFi_eeb21e;
const { Button: BtnC, Badge: BadgeC, Skeleton: SkeletonC } = DSc;

// Caixa de estado de carregamento: Skeleton enquanto carrega, mensagem + "Tentar de novo" no
// erro (com o motivo quando o servidor manda um), senão renderiza o conteúdo.
function CargaBox({ carregando, erro, onTentar, linhas, children }) {
 if (carregando) {
  return <div style={{ display: 'grid', gap: 8 }}>
   {Array.from({ length: linhas || 3 }).map((_, i) => <SkeletonC key={i} style={{ height: 44, borderRadius: 'var(--radius-lg)' }} />)}
  </div>;
 }
 if (erro) {
  const motivo = (erro && erro.corpo && erro.corpo.detail) || (erro && erro.status === 401 ? 'sessão expirada — recarregue a página' : (erro && erro.status ? 'erro ' + erro.status : 'falha de rede'));
  return <div style={{ border: '1px solid hsl(var(--border))', borderRadius: 'var(--radius-lg)', padding: 16, background: 'hsl(var(--card))', fontSize: 13.5, color: 'hsl(var(--muted-foreground))' }}>
   Não foi possível carregar: {motivo}.
   {onTentar ? <div style={{ marginTop: 10 }}><BtnC variant="outline" onClick={onTentar}>Tentar de novo</BtnC></div> : null}
  </div>;
 }
 return children;
}

const GESTAO_ICONES = {
 grid: '<rect x="3" y="3" width="7" height="7" rx="1"></rect><rect x="14" y="3" width="7" height="7" rx="1"></rect><rect x="3" y="14" width="7" height="7" rx="1"></rect><rect x="14" y="14" width="7" height="7" rx="1"></rect>',
 lista: '<circle cx="4.5" cy="6" r="1"></circle><line x1="9" y1="6" x2="20" y2="6"></line><circle cx="4.5" cy="12" r="1"></circle><line x1="9" y1="12" x2="20" y2="12"></line><circle cx="4.5" cy="18" r="1"></circle><line x1="9" y1="18" x2="20" y2="18"></line>',
 escudo: '<path d="M20 13c0 5-3.5 7.5-8 9-4.5-1.5-8-4-8-9V6l8-3 8 3z"></path>',
 wifi: '<path d="M5 12.55a11 11 0 0 1 14.08 0"></path><path d="M1.42 9a16 16 0 0 1 21.16 0"></path><path d="M8.53 16.11a6 6 0 0 1 6.95 0"></path><line x1="12" y1="20" x2="12.01" y2="20"></line>',
 tela: '<rect x="2" y="3" width="20" height="14" rx="2"></rect><line x1="8" y1="21" x2="16" y2="21"></line><line x1="12" y1="17" x2="12" y2="21"></line>',
 mail: '<rect x="2" y="4" width="20" height="16" rx="2"></rect><path d="m22 7-10 5L2 7"></path>',
 cpu: '<rect x="5" y="5" width="14" height="14" rx="2"></rect><rect x="10" y="10" width="4" height="4"></rect><path d="M9 2v3M15 2v3M9 19v3M15 19v3M2 9h3M2 15h3M19 9h3M19 15h3"></path>',
 atividade: '<polyline points="22 12 18 12 15 21 9 3 6 12 2 12"></polyline>'
};
function Icone({ nome, size = 16 }) {
 return <svg viewBox="0 0 24 24" width={size} height={size} fill="none" stroke="currentColor" strokeWidth="1.8" strokeLinecap="round" strokeLinejoin="round" style={{ flex: 'none' }} dangerouslySetInnerHTML={{ __html: GESTAO_ICONES[nome] }} />;
}

const GESTAO_DOT = { online: '#22c55e', ativo: '#22c55e', offline: 'hsl(var(--destructive))', aviso: 'hsl(var(--ring))', dormente: 'hsl(var(--muted-foreground))' };
function Dot({ s }) {
 return <span style={{ display: 'inline-flex', alignItems: 'center', gap: 6, fontSize: 13 }}>
  <span style={{ width: 8, height: 8, borderRadius: 9999, background: GESTAO_DOT[s] || GESTAO_DOT.aviso, flex: 'none' }} />{s}
 </span>;
}

function GTh({ children, right }) { return <th style={{ textAlign: right ? 'right' : 'left', padding: '8px 10px', color: 'hsl(var(--muted-foreground))', fontWeight: 600, fontSize: 12, borderBottom: '1px solid hsl(var(--border))', whiteSpace: 'nowrap' }}>{children}</th>; }
function GTd({ children, mono, right, wrap }) { return <td style={{ padding: '9px 10px', borderBottom: '1px solid hsl(var(--border))', fontSize: 13, textAlign: right ? 'right' : 'left', fontFamily: mono ? 'var(--app-font-mono)' : 'var(--app-font-sans)', whiteSpace: wrap ? 'normal' : 'nowrap', verticalAlign: 'top' }}>{children}</td>; }

function ChipFiltro({ ativo, onClick, children }) {
 return <button onClick={onClick} className="hover-elevate" style={{ background: ativo ? 'hsl(var(--accent))' : 'hsl(var(--card))', color: 'hsl(var(--foreground))', border: '1px solid ' + (ativo ? 'hsl(var(--ring))' : 'hsl(var(--border))'), borderRadius: 9999, padding: '5px 13px', fontSize: 12.5, cursor: 'pointer', fontFamily: 'var(--app-font-sans)' }}>{children}</button>;
}

function BtnMini({ children, tom, ...p }) {
 const cor = tom === 'perigo' ? 'hsl(var(--destructive))' : 'var(--brand-orange-text)';
 return <button {...p} className="hover-elevate" style={{ background: 'hsl(var(--card))', color: cor, border: '1px solid hsl(var(--border))', borderRadius: 'var(--radius-md)', padding: '5px 11px', fontSize: 12.5, fontWeight: 600, cursor: 'pointer', fontFamily: 'var(--app-font-sans)', whiteSpace: 'nowrap' }}>{children}</button>;
}

function TermoDica({ dica, children }) { return <span className="term" title={dica}>{children}</span>; }

function SelectG(p) {
 return <select {...p} style={{ background: 'hsl(var(--card))', color: 'hsl(var(--foreground))', border: '1px solid hsl(var(--input))', borderRadius: 'var(--radius-md)', padding: '8px 10px', fontSize: 13.5, fontFamily: 'var(--app-font-sans)', width: '100%', boxSizing: 'border-box', ...p.style }}>{p.children}</select>;
}

// Painel lateral: comando gerado para revisão — a interface NÃO executa escrita.
function CmdPainel({ cmd, onClose }) {
 const [copiado, setCopiado] = React.useState(false);
 const [exec, setExec] = React.useState({ estado: 'idle' }); // idle | executando | ok | erro
 React.useEffect(() => { setCopiado(false); setExec({ estado: 'idle' }); }, [cmd]);
 if (!cmd) return null;
 const texto = cmd.linhas.join('\n');
 const copiar = () => {
  try { navigator.clipboard.writeText(texto).then(() => setCopiado(true)); }
  catch (e) { setCopiado(false); }
 };
 // Executa só quando o ponto está no piloto (GESTAO_ESCRITA) e o comando declara uma ação.
 const podeExecutar = !!(cmd.slug && window.GESTAO_ESCRITA[cmd.slug] && cmd.acao);
 const executar = async () => {
  setExec({ estado: 'executando' });
  try {
   const API = window.GestaoAPI; let r;
   if (cmd.acao === 'binding-add') r = await API.bindingAdd(cmd.slug, cmd.mac, cmd.comment);
   else if (cmd.acao === 'binding-del') r = await API.bindingDel(cmd.slug, cmd.mac);
   else if (cmd.acao === 'ssid-add') r = await API.ssidAdd(cmd.slug, { nome: cmd.nome, banda: cmd.banda, seg: cmd.seg });
   else if (cmd.acao === 'ssid-bridge') r = await API.ssidBridge(cmd.slug, { cfg: cmd.cfg, bridge: cmd.bridge });
   else throw new Error('ação desconhecida');
   setExec({ estado: 'ok', saida: (r && (r.saida || r.nota)) || 'Executado.' });
   if (cmd.onSucesso) cmd.onSucesso();
  } catch (e) {
   const msg = (e && e.corpo && e.corpo.detail) || (e && e.status ? 'erro ' + e.status : 'falha de rede');
   setExec({ estado: 'erro', saida: msg });
  }
 };
 return <div onClick={onClose} style={{ position: 'fixed', inset: 0, background: 'rgba(15,23,42,.32)', display: 'flex', justifyContent: 'flex-end', zIndex: 60 }}>
  <div onClick={e => e.stopPropagation()} style={{ width: 480, maxWidth: '92vw', height: '100%', background: 'hsl(var(--card))', borderLeft: '1px solid hsl(var(--card-border))', boxShadow: 'var(--shadow-lg)', display: 'flex', flexDirection: 'column', boxSizing: 'border-box' }}>
   <div style={{ padding: '18px 22px 12px', borderBottom: '1px solid hsl(var(--border))' }}>
    <div style={{ display: 'flex', alignItems: 'center', gap: 10 }}>
     <div style={{ fontFamily: 'var(--app-font-display)', fontWeight: 700, fontSize: 17, flex: 1 }}>{cmd.titulo}</div>
     <button type="button" onClick={onClose} aria-label="Fechar" style={{ background: 'transparent', border: 'none', fontSize: 20, cursor: 'pointer', color: 'hsl(var(--muted-foreground))', lineHeight: 1 }}>×</button>
    </div>
    <div style={{ fontSize: 12.5, color: 'hsl(var(--muted-foreground))', marginTop: 4 }}>{podeExecutar ? `Alvo: ${cmd.alvo} · executa no roteador (piloto MF)` : `Alvo: ${cmd.alvo} · comando para o seu terminal`}</div>
   </div>
   <div style={{ padding: '16px 22px', overflowY: 'auto', flex: 1 }}>
    {cmd.linhas.map((l, i) => <pre key={i} style={{ background: 'hsl(var(--secondary))', border: '1px solid hsl(var(--border))', borderRadius: 'var(--radius-lg)', padding: '12px 14px', fontFamily: 'var(--app-font-mono)', fontSize: 12, lineHeight: 1.55, whiteSpace: 'pre-wrap', wordBreak: 'break-word', margin: '0 0 10px' }}>{l}</pre>)}
    {cmd.nota ? <div style={{ fontSize: 12.5, color: 'hsl(var(--muted-foreground))', lineHeight: 1.5 }}>{cmd.nota}</div> : null}
    {exec.estado === 'ok' ? <div style={{ marginTop: 14, background: 'hsl(var(--secondary))', border: '1px solid #22c55e', borderRadius: 'var(--radius-lg)', padding: '12px 14px', fontSize: 12, fontFamily: 'var(--app-font-mono)', whiteSpace: 'pre-wrap', wordBreak: 'break-word' }}>✓ {exec.saida}</div> : null}
    {exec.estado === 'erro' ? <div style={{ marginTop: 14, background: 'hsl(var(--secondary))', border: '1px solid hsl(var(--destructive))', borderRadius: 'var(--radius-lg)', padding: '12px 14px', fontSize: 13, color: 'hsl(var(--destructive))' }}>Não executado: {exec.saida}</div> : null}
   </div>
   <div style={{ padding: '14px 22px 18px', borderTop: '1px solid hsl(var(--border))', display: 'flex', gap: 10, alignItems: 'center', flexWrap: 'wrap' }}>
    {podeExecutar
     ? <BtnC onClick={executar} disabled={exec.estado === 'executando' || exec.estado === 'ok'}>{exec.estado === 'executando' ? 'Executando…' : (exec.estado === 'ok' ? 'Feito ✓' : 'Executar no roteador')}</BtnC>
     : null}
    <BtnC variant="outline" onClick={copiar}>{copiado ? 'Copiado ✓' : 'Copiar comandos'}</BtnC>
    <BtnC variant="outline" onClick={onClose}>Fechar</BtnC>
    {!podeExecutar ? <div style={{ fontSize: 11.5, color: 'hsl(var(--muted-foreground))', flex: 1, textAlign: 'right' }}>Fora do piloto MF: execute no seu terminal.</div> : null}
   </div>
  </div>
 </div>;
}

function mkLinha(alvo, comando) { return `app/.venv/bin/python ops/mk.py ${alvo} cmd '${comando}'`; }
function slugSsid(t) { return (t || '').toLowerCase().normalize('NFD').replace(/[̀-ͯ]/g, '').replace(/[^a-z0-9]+/g, '-').replace(/(^-|-$)/g, ''); }

// Menu de seleção de pontos — um ou vários clientes ao mesmo tempo.
function PontoMenu({ sel, setSel }) {
 const sites = window.GESTAO_META;
 const chaves = Object.keys(sites);
 const [aberto, setAberto] = React.useState(false);
 const todos = sel.length === chaves.length;
 const rotulo = todos ? 'Todos os pontos' : sel.length === 1 ? sites[sel[0]].label : `${sel.length} pontos`;
 const alterna = k => setSel(s => s.includes(k) ? (s.length > 1 ? s.filter(x => x !== k) : s) : [...s, k]);
 return <div style={{ position: 'relative' }}>
  <button onClick={() => setAberto(a => !a)} className="hover-elevate" aria-haspopup="true" aria-expanded={aberto} style={{ display: 'flex', alignItems: 'center', gap: 10, background: 'hsl(var(--card))', border: '1px solid hsl(var(--border))', borderRadius: 'var(--radius-md)', padding: '7px 12px', fontSize: 13, fontFamily: 'var(--app-font-sans)', color: 'hsl(var(--foreground))', cursor: 'pointer', minWidth: 176, justifyContent: 'space-between' }}>
   <span style={{ fontWeight: 600 }}>{rotulo}</span>
   <svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" style={{ color: 'hsl(var(--muted-foreground))', transform: aberto ? 'rotate(180deg)' : 'none', transition: 'transform .15s ease' }}><path d="m6 9 6 6 6-6"></path></svg>
  </button>
  {aberto ? <div>
   <div onClick={() => setAberto(false)} style={{ position: 'fixed', inset: 0, zIndex: 40 }} />
   <div style={{ position: 'absolute', right: 0, top: 'calc(100% + 6px)', zIndex: 41, background: 'hsl(var(--popover))', border: '1px solid hsl(var(--popover-border))', borderRadius: 'var(--radius-lg)', boxShadow: 'var(--shadow-md)', padding: 6, width: 232 }}>
    <label className="hover-elevate" style={{ display: 'flex', alignItems: 'center', gap: 10, padding: '8px 10px', borderRadius: 'var(--radius-md)', cursor: 'pointer', fontSize: 13, fontWeight: 600 }}>
     <input type="checkbox" checked={todos} onChange={() => setSel(todos ? [chaves[0]] : chaves)} style={{ accentColor: 'hsl(var(--primary))', width: 15, height: 15, flex: 'none' }} />Todos os pontos
    </label>
    <div style={{ height: 1, background: 'hsl(var(--border))', margin: '4px 6px' }} />
    {chaves.map(k => <label key={k} className="hover-elevate" style={{ display: 'flex', alignItems: 'center', gap: 10, padding: '8px 10px', borderRadius: 'var(--radius-md)', cursor: 'pointer', fontSize: 13 }}>
     <input type="checkbox" checked={sel.includes(k)} onChange={() => alterna(k)} style={{ accentColor: 'hsl(var(--primary))', width: 15, height: 15, flex: 'none' }} />
     <span style={{ flex: 1 }}>{sites[k].label}</span>
     <span style={{ fontSize: 11, color: 'hsl(var(--muted-foreground))' }}>{sites[k].tipo}</span>
    </label>)}
   </div>
  </div> : null}
 </div>;
}

Object.assign(window, { Icone, Dot, GTh, GTd, ChipFiltro, BtnMini, TermoDica, SelectG, CmdPainel, PontoMenu, mkLinha, slugSsid, CargaBox });
