// ui-lib.jsx — Shared UI components: icons, charts, inputs, overlays
const { useState, useRef, useEffect, useMemo, useCallback } = React;

/* ═══════════════════ ICONS (solid, minimal) ═══════════════════ */
const Ico = ({d, size=14, className='', style={}}) => (
  <svg width={size} height={size} viewBox="0 0 16 16" fill="currentColor" style={{flexShrink:0,...style}} className={className}>
    <path d={d}/>
  </svg>
);

const IcoSearch = (p) => <Ico {...p} d="M11.742 10.344a6.5 6.5 0 1 0-1.397 1.398h-.001l3.85 3.85a1 1 0 0 0 1.415-1.414l-3.85-3.85zm-5.242.156a5 5 0 1 1 0-10 5 5 0 0 1 0 10z"/>;
const IcoClose = (p) => <Ico {...p} d="M4.646 4.646a.5.5 0 0 1 .708 0L8 7.293l2.646-2.647a.5.5 0 0 1 .708.708L8.707 8l2.647 2.646a.5.5 0 0 1-.708.708L8 8.707l-2.646 2.647a.5.5 0 0 1-.708-.708L7.293 8 4.646 5.354a.5.5 0 0 1 0-.708z"/>;
const IcoChevRight = (p) => <Ico {...p} d="M6.776 1.553a.5.5 0 0 1 .671.223l.04.08L11 8l-3.513 6.145a.5.5 0 0 1-.932-.367l.031-.078L9.72 8 6.586 2.3a.5.5 0 0 1 .19-.747z"/>;
const IcoChevDown = (p) => <Ico {...p} d="M1.553 6.776a.5.5 0 0 1 .747-.223L8 9.72l5.7-3.134a.5.5 0 0 1 .522.87l-.078.04L8 11l-6.145-3.504a.5.5 0 0 1-.302-.72z"/>;
const IcoExport = (p) => <Ico {...p} d="M.5 9.9a.5.5 0 0 1 .5.5v2.5a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1v-2.5a.5.5 0 0 1 1 0v2.5a2 2 0 0 1-2 2H2a2 2 0 0 1-2-2v-2.5a.5.5 0 0 1 .5-.5zm7.982-8.372a.5.5 0 0 1 .036.018l3 1.75a.5.5 0 1 1-.504.864L8.5 3.073V10.5a.5.5 0 1 1-1 0V3.073L4.986 4.16a.5.5 0 1 1-.504-.864l3-1.75a.5.5 0 0 1 .518.018l-.018-.036z"/>;
const IcoChart = (p) => <Ico {...p} d="M0 0h1v15h15v1H0V0zm14.817 3.113a.5.5 0 0 1 .07.704l-4.5 5.5a.5.5 0 0 1-.74.037L7.06 6.767l-3.656 5.027a.5.5 0 0 1-.808-.588l4-5.5a.5.5 0 0 1 .758-.06l2.609 2.61 4.15-5.073a.5.5 0 0 1 .704-.07z"/>;
const IcoSave = (p) => <Ico {...p} d="M2 1a1 1 0 0 0-1 1v12a1 1 0 0 0 1 1h12a1 1 0 0 0 1-1V4.414A2 2 0 0 0 14.414 3L12 .586A2 2 0 0 0 10.586 0H2zm0 1h8.586L13 4.414V14H2V2zm2 8h8v3H4v-3zm1 1v1h6v-1H5zm0-5h6a.5.5 0 0 1 0 1H5a.5.5 0 0 1 0-1z"/>;
const IcoHistory = (p) => <Ico {...p} d="M8 3.5a.5.5 0 0 0-1 0V8a.5.5 0 0 0 .252.434l3.5 2a.5.5 0 0 0 .496-.868L8 7.71V3.5zM8 16A8 8 0 1 0 8 0a8 8 0 0 0 0 16zm7-8A7 7 0 1 1 1 8a7 7 0 0 1 14 0z"/>;
const IcoEdit = (p) => <Ico {...p} d="M12.146.146a.5.5 0 0 1 .708 0l3 3a.5.5 0 0 1 0 .708l-10 10a.5.5 0 0 1-.168.11l-5 2a.5.5 0 0 1-.65-.65l2-5a.5.5 0 0 1 .11-.168l10-10zM11.207 2.5L13.5 4.793 14.793 3.5 12.5 1.207 11.207 2.5zm1.586 3L10.5 3.207 4 9.707V10h.5a.5.5 0 0 1 .5.5v.5h.5a.5.5 0 0 1 .5.5v.5h.293l6.5-6.5z"/>;
const IcoTrash = (p) => <Ico {...p} d="M5.5 5.5A.5.5 0 0 1 6 6v6a.5.5 0 0 1-1 0V6a.5.5 0 0 1 .5-.5zm2.5 0a.5.5 0 0 1 .5.5v6a.5.5 0 0 1-1 0V6a.5.5 0 0 1 .5-.5zm3 .5a.5.5 0 0 0-1 0v6a.5.5 0 0 0 1 0V6zm-9-3a1 1 0 0 1 1-1h8a1 1 0 0 1 1 1v1H2V3zm10 1V3h-1V2H5v1H4v1h8z"/>;
const IcoCheck = (p) => <Ico {...p} d="M13.854 3.646a.5.5 0 0 1 0 .708l-7 7a.5.5 0 0 1-.708 0l-3.5-3.5a.5.5 0 1 1 .708-.708L6.5 10.293l6.646-6.647a.5.5 0 0 1 .708 0z"/>;
const IcoLink = (p) => <Ico {...p} d="M4.715 6.542L3.343 7.914a3 3 0 1 0 4.243 4.243l1.828-1.829A3 3 0 0 0 8.586 5.5L8 6.086a1 1 0 0 0-.154.199 2 2 0 0 1 .861 3.337L6.88 11.45a2 2 0 1 1-2.83-2.83l.793-.792a4 4 0 0 1-.128-1.287zM6.586 4.672A3 3 0 0 0 7.414 9.5l.586-.586a1 1 0 0 0 .154-.199 2 2 0 0 1-.861-3.337L9.12 3.55a2 2 0 1 1 2.83 2.83l-.793.792c.112.42.155.855.128 1.287l1.372-1.372a3 3 0 1 0-4.243-4.243L6.586 4.672z"/>;
const IcoNote = (p) => <Ico {...p} d="M5 0h8a2 2 0 0 1 2 2v10a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2V2a2 2 0 0 1 2-2zm0 1a1 1 0 0 0-1 1v10a1 1 0 0 0 1 1h8a1 1 0 0 0 1-1V2a1 1 0 0 0-1-1H5zm1 3h6v1H6V4zm0 3h6v1H6V7zm0 3h4v1H6v-1z"/>;
const IcoSort = ({dir, ...p}) => <Ico {...p} d={dir==='asc'?"M8 1l4 5H4l4-5zm0 14l-4-5h8l-4 5z":dir==='desc'?"M8 15l-4-5h8l-4 5zm0-14l4 5H4l4-5z":"M8 1l4 5H4l4-5zm0 14l-4-5h8l-4 5z"}/>;
const IcoFilter = (p) => <Ico {...p} d="M1.5 1.5A.5.5 0 0 1 2 1h12a.5.5 0 0 1 .376.832L10 7.397V13.5a.5.5 0 0 1-.223.416l-3 2A.5.5 0 0 1 6 15.5V7.397L1.624 1.832A.5.5 0 0 1 1.5 1.5z"/>;
const IcoShare = (p) => <Ico {...p} d="M11 2.5a2.5 2.5 0 1 1 .603 1.628l-6.718 3.12a2.499 2.499 0 0 1 0 1.504l6.718 3.12a2.5 2.5 0 1 1-.488.876l-6.718-3.12a2.5 2.5 0 1 1 0-3.256l6.718-3.12A2.5 2.5 0 0 1 11 2.5z"/>;
const IcoCopy = (p) => <Ico {...p} d="M4 1.5H3a2 2 0 0 0-2 2V14a2 2 0 0 0 2 2h10a2 2 0 0 0 2-2V3.5a2 2 0 0 0-2-2h-1v1h1a1 1 0 0 1 1 1V14a1 1 0 0 1-1 1H3a1 1 0 0 1-1-1V3.5a1 1 0 0 1 1-1h1v-1z M9.5 1a.5.5 0 0 1 .5.5v1a.5.5 0 0 1-.5.5h-3a.5.5 0 0 1-.5-.5v-1a.5.5 0 0 1 .5-.5h3zm-3-1A1.5 1.5 0 0 0 5 1.5v1A1.5 1.5 0 0 0 6.5 4h3A1.5 1.5 0 0 0 11 2.5v-1A1.5 1.5 0 0 0 9.5 0h-3z"/>;

/* ═══════════════════ NUMBER FORMAT ═══════════════════ */
function fmtNum(n) {
  if (n == null) return '—';
  return n.toLocaleString('pt-BR');
}

/* ═══════════════════ SEARCHABLE MULTI-SELECT ═══════════════════ */
function SearchableSelect({ label, options, selected, onChange, mono }) {
  const [open, setOpen] = useState(false);
  const [q, setQ] = useState('');
  const ref = useRef(null);

  useEffect(() => {
    const handler = (e) => { if (ref.current && !ref.current.contains(e.target)) setOpen(false); };
    document.addEventListener('mousedown', handler);
    return () => document.removeEventListener('mousedown', handler);
  }, []);

  const filtered = options.filter(o => String(o).toLowerCase().includes(q.toLowerCase()));
  const toggle = (val) => {
    const s = new Set(selected);
    s.has(val) ? s.delete(val) : s.add(val);
    onChange([...s]);
  };

  const ssStyles = {
    wrap: { position:'relative', marginBottom: 'var(--sp-3)' },
    header: {
      display:'flex', alignItems:'center', justifyContent:'space-between',
      padding:'6px 0', cursor:'pointer', userSelect:'none',
      fontSize:'0.923rem', fontWeight:600, color:'var(--text-1)', letterSpacing:'0.01em'
    },
    count: {
      fontSize:'0.77rem', fontFamily:'var(--font-mono)', background:'var(--accent-subtle)',
      color:'var(--accent-text)', padding:'1px 6px', borderRadius:'var(--radius-sm)', fontWeight:500
    },
    dropdown: {
      position:'absolute', left:0, right:0, top:'100%', zIndex:20,
      background:'var(--bg-1)', border:'1px solid var(--border-0)',
      borderRadius:'var(--radius-md)', boxShadow:'0 4px 12px rgba(0,0,0,.12)',
      maxHeight: 260, overflowY:'auto', padding:'var(--sp-2)'
    },
    searchInput: {
      width:'100%', padding:'6px 8px', border:'1px solid var(--border-1)',
      borderRadius:'var(--radius-sm)', background:'var(--bg-2)', color:'var(--text-0)',
      fontSize:'0.923rem', outline:'none', marginBottom:'var(--sp-2)',
      fontFamily: 'var(--font-sans)'
    },
    option: (isSelected) => ({
      display:'flex', alignItems:'center', gap:'var(--sp-2)',
      padding:'5px 8px', cursor:'pointer', borderRadius:'var(--radius-sm)',
      fontSize:'0.923rem', color: isSelected ? 'var(--accent-text)' : 'var(--text-1)',
      background: isSelected ? 'var(--accent-subtle)' : 'transparent',
      fontFamily: mono ? 'var(--font-mono)' : 'inherit'
    })
  };

  return (
    <div ref={ref} style={ssStyles.wrap}>
      <div style={ssStyles.header} onClick={() => setOpen(!open)}>
        <span>{label}</span>
        <span style={{display:'flex',alignItems:'center',gap:'var(--sp-1)'}}>
          {selected.length > 0 && <span style={ssStyles.count}>{selected.length}</span>}
          <IcoChevDown size={10} style={{transform: open?'rotate(180deg)':'none', transition:'transform var(--tr-fast)'}}/>
        </span>
      </div>
      {open && (
        <div style={ssStyles.dropdown}>
          <input style={ssStyles.searchInput} placeholder="Filtrar..." value={q} onChange={e=>setQ(e.target.value)} autoFocus/>
          {filtered.map(o => (
            <div key={o} style={ssStyles.option(selected.includes(o))} onClick={()=>toggle(o)}
              onMouseEnter={e=>e.currentTarget.style.background=selected.includes(o)?'var(--accent-subtle)':'var(--bg-hover)'}
              onMouseLeave={e=>e.currentTarget.style.background=selected.includes(o)?'var(--accent-subtle)':'transparent'}>
              <span style={{width:12,height:12,border:'1.5px solid '+(selected.includes(o)?'var(--accent)':'var(--border-0)'),borderRadius:'var(--radius-sm)',display:'flex',alignItems:'center',justifyContent:'center',background:selected.includes(o)?'var(--accent)':'transparent',flexShrink:0}}>
                {selected.includes(o) && <IcoCheck size={8} style={{color:'#fff'}}/>}
              </span>
              <span className="truncate" style={{flex:1}}>{String(o)}</span>
            </div>
          ))}
          {filtered.length === 0 && <div style={{padding:'8px',color:'var(--text-3)',fontSize:'0.846rem',textAlign:'center'}}>Nenhum resultado</div>}
        </div>
      )}
    </div>
  );
}

/* ═══════════════════ BAR CHART ═══════════════════ */
function HBarChart({ data, maxItems=10, height, colorVar='--data-1', onBarClick }) {
  if (!data || !data.length) return null;
  const [expanded, setExpanded] = useState(null);
  const items = data.slice(0, maxItems);
  const maxVal = Math.max(...items.map(d=>d.valor), 1);
  const isMobile = typeof window !== 'undefined' && window.innerWidth < 768;
  const isDesktop = typeof window !== 'undefined' && window.innerWidth >= 1024;
  const barH = isDesktop ? 28 : 20;
  const gap = isMobile ? 10 : (isDesktop ? 6 : 4);
  const labelW = isMobile ? '40%' : (isDesktop ? 240 : 180);
  const valW = isMobile ? 60 : (isDesktop ? 80 : 50);
  const fontSize = isDesktop ? '0.923rem' : '0.77rem';
  const barFillH = isDesktop ? barH - 8 : barH - 6;

  const chartS = {
    wrap: { width:'100%' },
    row: (isExpanded) => ({ display:'flex', alignItems: isExpanded ? 'flex-start' : 'center', gap:'var(--sp-3)', marginBottom:gap, cursor:'pointer', padding: isExpanded ? '4px 0' : 0, borderRadius:'var(--radius-sm)' }),
    label: (isExpanded) => ({
      width:labelW, maxWidth: isMobile ? '40%' : (isDesktop ? 240 : 180),
      fontSize, color:'var(--text-1)',
      overflow: isExpanded ? 'visible' : 'hidden',
      textOverflow: isExpanded ? 'unset' : 'ellipsis',
      whiteSpace: isExpanded ? 'normal' : 'nowrap',
      wordBreak: isExpanded ? 'break-word' : 'normal',
      textAlign:'right', flexShrink:0,
      lineHeight: 1.4,
      paddingTop: isExpanded ? 2 : 0
    }),
    barBg: (isExpanded) => ({ flex:1, minWidth:20, height: barFillH, marginTop: isExpanded ? 4 : 0, background:'var(--bg-3)', borderRadius:'var(--radius-sm)', overflow:'hidden', position:'relative' }),
    bar: (pct) => ({ width: pct+'%', height:'100%', background:`var(${colorVar})`, borderRadius:'var(--radius-sm)', transition:'width 0.3s ease', minWidth: pct > 0 ? 2 : 0 }),
    val: (isExpanded) => ({ width:valW, fontSize, fontFamily:'var(--font-mono)', color:'var(--text-2)', textAlign:'right', flexShrink:0, marginTop: isExpanded ? 2 : 0, fontWeight: isDesktop ? 500 : 400 })
  };

  const handleClick = (i, d) => {
    setExpanded(prev => prev === i ? null : i);
    if (onBarClick) onBarClick(d);
  };

  return (
    <div style={chartS.wrap}>
      {items.map((d, i) => {
        const isExpanded = expanded === i;
        return (
          <div key={d.label} style={chartS.row(isExpanded)} onClick={() => handleClick(i, d)}>
            <div style={chartS.label(isExpanded)} title={d.label}>{d.label}</div>
            <div style={chartS.barBg(isExpanded)}>
              <div style={chartS.bar(d.valor / maxVal * 100)}/>
            </div>
            <div style={chartS.val(isExpanded)}>{fmtNum(d.valor)}</div>
          </div>
        );
      })}
    </div>
  );
}

/* ═══════════════════ TIMELINE CHART ═══════════════════ */
function TimelineChart({ data, height=100 }) {
  if (!data || !data.length) return null;
  const maxVal = Math.max(...data.map(d=>d.valor), 1);
  const isDesktop = typeof window !== 'undefined' && window.innerWidth >= 1024;
  const pad = { top: 10, bottom: isDesktop ? 28 : 20, left: 6, right: 6 };

  const barWidth = isDesktop
    ? Math.max(20, Math.min(56, 600 / data.length))
    : Math.max(12, Math.min(36, 300 / data.length));
  const gap = isDesktop ? 6 : 3;
  const totalW = data.length * (barWidth + gap);
  const labelFontSize = isDesktop ? 12 : 9;

  return (
    <div style={{width:'100%', overflowX:'auto', overflowY:'hidden'}}>
      <svg width={Math.max(totalW + pad.left + pad.right, 100)} height={height} style={{display:'block'}}>
        {data.map((d, i) => {
          const x = pad.left + i * (barWidth + gap);
          const barH = (d.valor / maxVal) * (height - pad.top - pad.bottom);
          const y = height - pad.bottom - barH;
          return (
            <g key={d.label}>
              <rect x={x} y={y} width={barWidth} height={barH} fill="var(--data-1)" rx={2} opacity={0.85}/>
              <text x={x + barWidth/2} y={height - (isDesktop ? 8 : 4)} textAnchor="middle" fill="var(--text-3)"
                style={{fontSize: labelFontSize + 'px', fontFamily:'var(--font-mono)'}}>{isDesktop ? d.label : d.label.slice(-2)}</text>
              <title>{d.label}: {fmtNum(d.valor)}</title>
            </g>
          );
        })}
      </svg>
    </div>
  );
}

/* ═══════════════════ SKELETON ROWS ═══════════════════ */
function SkeletonRows({ count=8 }) {
  return Array.from({length:count}).map((_,i) => (
    <div key={i} style={{display:'flex',gap:'var(--sp-3)',padding:'var(--cell-py, 6px) var(--sp-3)',borderBottom:'1px solid var(--border-1)'}}>
      <div className="skeleton" style={{width:60,height:14}}/>
      <div className="skeleton" style={{width:50,height:14}}/>
      <div className="skeleton" style={{flex:1,height:14}}/>
      <div className="skeleton" style={{width:40,height:14}}/>
      <div className="skeleton" style={{width:100,height:14}}/>
    </div>
  ));
}

/* ═══════════════════ EMPTY STATE ═══════════════════ */
function EmptyState({ message, sub }) {
  const isDesktop = typeof window !== 'undefined' && window.innerWidth >= 1024;
  return (
    <div style={{
      display:'flex', flexDirection:'column', alignItems:'center', justifyContent:'center',
      padding: isDesktop ? '120px var(--sp-10)' : 'var(--sp-10)',
      color:'var(--text-3)',
      gap: isDesktop ? 'var(--sp-3)' : 'var(--sp-2)',
      flex: 1
    }}>
      <div style={{
        fontSize: isDesktop ? '1.846rem' : '1.077rem',
        fontWeight: isDesktop ? 600 : 500,
        color:'var(--text-2)',
        letterSpacing: isDesktop ? '-0.01em' : 0,
        textAlign:'center'
      }}>
        {message || 'Nenhum resultado'}
      </div>
      {sub && (
        <div style={{
          fontSize: isDesktop ? '1.077rem' : '0.846rem',
          color:'var(--text-3)',
          textAlign:'center',
          maxWidth: 460,
          lineHeight: 1.5
        }}>
          {sub}
        </div>
      )}
    </div>
  );
}

/* ═══════════════════ MODAL ═══════════════════ */
function Modal({ open, title, onClose, children, footer, maxWidth=460 }) {
  useEffect(() => {
    if (!open) return;
    const handler = (e) => { if (e.key === 'Escape') { e.stopPropagation(); onClose && onClose(); } };
    window.addEventListener('keydown', handler);
    return () => window.removeEventListener('keydown', handler);
  }, [open, onClose]);
  if (!open) return null;

  return (
    <div
      style={{
        position:'fixed', inset:0, background:'rgba(0,0,0,0.45)', zIndex:200,
        display:'flex', alignItems:'center', justifyContent:'center',
        padding:'var(--sp-4)', animation:'fadeIn 140ms ease'
      }}
      onClick={onClose}>
      <div
        onClick={e => e.stopPropagation()}
        role="dialog"
        aria-modal="true"
        style={{
          background:'var(--bg-1)', border:'1px solid var(--border-0)',
          borderRadius:'var(--radius-md)', maxWidth, width:'100%',
          boxShadow:'0 12px 48px rgba(0,0,0,0.22)',
          display:'flex', flexDirection:'column', overflow:'hidden',
          maxHeight:'90vh'
        }}>
        {title && (
          <div style={{
            padding:'var(--sp-4) var(--sp-5)', borderBottom:'1px solid var(--border-1)',
            display:'flex', alignItems:'center', justifyContent:'space-between',
            background:'var(--bg-2)'
          }}>
            <span style={{fontWeight:600, fontSize:'1.077rem', color:'var(--text-0)'}}>{title}</span>
            <span style={{cursor:'pointer', color:'var(--text-2)', display:'flex'}} onClick={onClose} title="Fechar">
              <IcoClose size={14}/>
            </span>
          </div>
        )}
        <div style={{padding:'var(--sp-5)', overflowY:'auto'}}>
          {children}
        </div>
        {footer && (
          <div style={{
            padding:'var(--sp-3) var(--sp-5)', borderTop:'1px solid var(--border-1)',
            display:'flex', justifyContent:'flex-end', gap:'var(--sp-2)',
            background:'var(--bg-2)'
          }}>
            {footer}
          </div>
        )}
      </div>
    </div>
  );
}

/* ═══════════════════ CONFIRM DIALOG ═══════════════════ */
function ConfirmDialog({ open, title, message, confirmLabel='Confirmar', cancelLabel='Cancelar', destructive, onConfirm, onCancel }) {
  const confirmBtnRef = useRef(null);
  useEffect(() => { if (open && confirmBtnRef.current) confirmBtnRef.current.focus(); }, [open]);

  const dangerBtnStyle = destructive
    ? { background:'var(--danger)', borderColor:'var(--danger)', color:'#fff' }
    : undefined;

  return (
    <Modal open={open} title={title || 'Confirmar'} onClose={onCancel}
      footer={<>
        <button className="btn" onClick={onCancel}>{cancelLabel}</button>
        <button ref={confirmBtnRef} className="btn btn-primary" style={dangerBtnStyle} onClick={onConfirm}>
          {confirmLabel}
        </button>
      </>}>
      <div style={{fontSize:'1rem', color:'var(--text-1)', lineHeight:1.55}}>{message}</div>
    </Modal>
  );
}

/* ═══════════════════ PROMPT DIALOG ═══════════════════ */
function PromptDialog({ open, title, message, defaultValue='', placeholder, confirmLabel='Salvar', cancelLabel='Cancelar', onConfirm, onCancel }) {
  const [val, setVal] = useState(defaultValue);
  const inputRef = useRef(null);
  useEffect(() => { setVal(defaultValue || ''); }, [defaultValue, open]);
  useEffect(() => {
    if (open && inputRef.current) {
      // Defer focus so the modal animation doesn't fight the focus call
      const t = setTimeout(() => { inputRef.current && inputRef.current.focus(); inputRef.current && inputRef.current.select(); }, 30);
      return () => clearTimeout(t);
    }
  }, [open]);

  const submit = () => {
    const v = val.trim();
    if (v) onConfirm(v);
  };

  return (
    <Modal open={open} title={title || 'Entrada'} onClose={onCancel}
      footer={<>
        <button className="btn" onClick={onCancel}>{cancelLabel}</button>
        <button className="btn btn-primary" onClick={submit} disabled={!val.trim()}>{confirmLabel}</button>
      </>}>
      {message && (
        <div style={{fontSize:'0.923rem', color:'var(--text-2)', marginBottom:'var(--sp-3)', lineHeight:1.5}}>
          {message}
        </div>
      )}
      <input
        ref={inputRef}
        className="input"
        value={val}
        onChange={e => setVal(e.target.value)}
        placeholder={placeholder}
        onKeyDown={e => {
          if (e.key === 'Enter') submit();
          if (e.key === 'Escape') onCancel();
        }}
        style={{width:'100%', padding:'10px 12px', fontSize:'1rem'}}
      />
    </Modal>
  );
}

/* ═══════════════════ DIALOG HOOK ═══════════════════
 * Drop-in async replacement for window.confirm / window.prompt.
 *
 *   const ok = await dialog.confirm({ message: '...', destructive: true });
 *   const name = await dialog.prompt({ defaultValue: '...' });
 *
 * Returns `{ confirm, prompt, render }`. Render `dialog.render` once in your tree.
 */
function useDialog() {
  const [state, setState] = useState(null); // { type, props, resolve }

  const askConfirm = useCallback((opts) => new Promise(resolve => {
    setState({ type:'confirm', props:opts || {}, resolve });
  }), []);

  const askPrompt = useCallback((opts) => new Promise(resolve => {
    setState({ type:'prompt', props:opts || {}, resolve });
  }), []);

  const close = useCallback((value) => {
    setState(prev => {
      if (prev && prev.resolve) prev.resolve(value);
      return null;
    });
  }, []);

  const render = state && (
    state.type === 'confirm' ? (
      <ConfirmDialog open={true} {...state.props}
        onConfirm={() => close(true)} onCancel={() => close(false)}/>
    ) : state.type === 'prompt' ? (
      <PromptDialog open={true} {...state.props}
        onConfirm={(v) => close(v)} onCancel={() => close(null)}/>
    ) : null
  );

  return { confirm: askConfirm, prompt: askPrompt, render };
}

/* ═══════════════════ EXPORTS ═══════════════════ */
Object.assign(window, {
  Ico, IcoSearch, IcoClose, IcoChevRight, IcoChevDown, IcoExport, IcoChart, IcoSave,
  IcoHistory, IcoEdit, IcoTrash, IcoCheck, IcoLink, IcoNote, IcoSort, IcoFilter,
  IcoShare, IcoCopy,
  fmtNum, SearchableSelect, HBarChart, TimelineChart, SkeletonRows, EmptyState,
  Modal, ConfirmDialog, PromptDialog, useDialog
});
