// Common small components + helpers

const { useState, useEffect, useMemo, useRef } = React;

const STATUS_LABEL = {
  pending: '대기',
  approved: '승인',
  scheduled: '예약됨',
  published: '게시완료',
  failed: '실패',
  held: '보류',
  draft: '작성중',
};

const STATUS_ORDER = ['pending', 'approved', 'scheduled', 'published'];

function fmtTime(iso) {
  if (!iso) return '—';
  const d = new Date(iso);
  const mo = String(d.getMonth()+1).padStart(2,'0');
  const dd = String(d.getDate()).padStart(2,'0');
  const hh = String(d.getHours()).padStart(2,'0');
  const mm = String(d.getMinutes()).padStart(2,'0');
  return `${mo}/${dd} ${hh}:${mm}`;
}
function fmtRelative(iso) {
  if (!iso) return '';
  const now = new Date('2026-04-20T14:30:00+09:00').getTime();
  const t = new Date(iso).getTime();
  const diff = Math.round((t - now) / 60000);
  const abs = Math.abs(diff);
  if (abs < 1) return '방금';
  if (abs < 60) return diff < 0 ? `${abs}분 전` : `${abs}분 후`;
  const h = Math.round(abs/60);
  if (h < 24) return diff < 0 ? `${h}시간 전` : `${h}시간 후`;
  const d = Math.round(h/24);
  return diff < 0 ? `${d}일 전` : `${d}일 후`;
}

function Badge({ status, children }) {
  const label = children || STATUS_LABEL[status] || status;
  return <span className={`badge ${status}`}><span className="dot"/>{label}</span>;
}

function Icon({ name, size = 14 }) {
  const paths = {
    search: <><circle cx="11" cy="11" r="7"/><path d="m21 21-4.3-4.3"/></>,
    plus: <><path d="M12 5v14M5 12h14"/></>,
    bell: <><path d="M6 8a6 6 0 0 1 12 0c0 7 3 9 3 9H3s3-2 3-9"/><path d="M10.3 21a1.94 1.94 0 0 0 3.4 0"/></>,
    settings: <><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.65 1.65 0 0 0 .33 1.82l.06.06a2 2 0 0 1 0 2.83 2 2 0 0 1-2.83 0l-.06-.06a1.65 1.65 0 0 0-1.82-.33 1.65 1.65 0 0 0-1 1.51V21a2 2 0 0 1-4 0v-.09A1.65 1.65 0 0 0 9 19.4a1.65 1.65 0 0 0-1.82.33l-.06.06a2 2 0 0 1-2.83 0 2 2 0 0 1 0-2.83l.06-.06a1.65 1.65 0 0 0 .33-1.82 1.65 1.65 0 0 0-1.51-1H3a2 2 0 0 1 0-4h.09A1.65 1.65 0 0 0 4.6 9a1.65 1.65 0 0 0-.33-1.82l-.06-.06a2 2 0 0 1 0-2.83 2 2 0 0 1 2.83 0l.06.06a1.65 1.65 0 0 0 1.82.33H9a1.65 1.65 0 0 0 1-1.51V3a2 2 0 0 1 4 0v.09a1.65 1.65 0 0 0 1 1.51 1.65 1.65 0 0 0 1.82-.33l.06-.06a2 2 0 0 1 2.83 0 2 2 0 0 1 0 2.83l-.06.06a1.65 1.65 0 0 0-.33 1.82V9a1.65 1.65 0 0 0 1.51 1H21a2 2 0 0 1 0 4h-.09a1.65 1.65 0 0 0-1.51 1z"/></>,
    home: <><path d="M3 9 12 2l9 7v11a2 2 0 0 1-2 2h-4v-8h-6v8H5a2 2 0 0 1-2-2z"/></>,
    calendar: <><rect x="3" y="4" width="18" height="18" rx="2"/><path d="M16 2v4M8 2v4M3 10h18"/></>,
    chat: <><path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z"/></>,
    users: <><path d="M17 21v-2a4 4 0 0 0-4-4H5a4 4 0 0 0-4 4v2"/><circle cx="9" cy="7" r="4"/><path d="M23 21v-2a4 4 0 0 0-3-3.87"/><path d="M16 3.13a4 4 0 0 1 0 7.75"/></>,
    check: <><path d="m5 12 5 5L20 7"/></>,
    x: <><path d="M18 6 6 18M6 6l12 12"/></>,
    chevronRight: <><path d="m9 18 6-6-6-6"/></>,
    chevronDown: <><path d="m6 9 6 6 6-6"/></>,
    play: <><polygon points="5 3 19 12 5 21 5 3"/></>,
    pause: <><rect x="6" y="4" width="4" height="16"/><rect x="14" y="4" width="4" height="16"/></>,
    more: <><circle cx="12" cy="12" r="1"/><circle cx="19" cy="12" r="1"/><circle cx="5" cy="12" r="1"/></>,
    edit: <><path d="M12 20h9"/><path d="M16.5 3.5a2.12 2.12 0 0 1 3 3L7 19l-4 1 1-4z"/></>,
    clock: <><circle cx="12" cy="12" r="10"/><path d="M12 6v6l4 2"/></>,
    eye: <><path d="M1 12s4-8 11-8 11 8 11 8-4 8-11 8-11-8-11-8z"/><circle cx="12" cy="12" r="3"/></>,
    heart: <><path d="M20.84 4.61a5.5 5.5 0 0 0-7.78 0L12 5.67l-1.06-1.06a5.5 5.5 0 0 0-7.78 7.78l1.06 1.06L12 21.23l7.78-7.78 1.06-1.06a5.5 5.5 0 0 0 0-7.78z"/></>,
    filter: <><polygon points="22 3 2 3 10 12.46 10 19 14 21 14 12.46 22 3"/></>,
    grid: <><rect x="3" y="3" width="7" height="7"/><rect x="14" y="3" width="7" height="7"/><rect x="3" y="14" width="7" height="7"/><rect x="14" y="14" width="7" height="7"/></>,
    list: <><line x1="8" y1="6" x2="21" y2="6"/><line x1="8" y1="12" x2="21" y2="12"/><line x1="8" y1="18" x2="21" y2="18"/><line x1="3" y1="6" x2="3.01" y2="6"/><line x1="3" y1="12" x2="3.01" y2="12"/><line x1="3" y1="18" x2="3.01" y2="18"/></>,
    columns: <><path d="M12 3v18M3 3h18v18H3z"/></>,
    refresh: <><path d="M21 12a9 9 0 1 1-3-6.7L21 8"/><path d="M21 3v5h-5"/></>,
    sparkle: <><path d="m12 3 2 5 5 2-5 2-2 5-2-5-5-2 5-2z"/></>,
    sun: <><circle cx="12" cy="12" r="4"/><path d="M12 2v2M12 20v2M4.93 4.93l1.41 1.41M17.66 17.66l1.41 1.41M2 12h2M20 12h2M6.34 17.66l-1.41 1.41M19.07 4.93l-1.41 1.41"/></>,
    moon: <><path d="M21 12.79A9 9 0 1 1 11.21 3 7 7 0 0 0 21 12.79z"/></>,
    send: <><path d="m22 2-7 20-4-9-9-4 20-7z"/></>,
    alert: <><path d="M12 9v4M12 17h.01M10.29 3.86 1.82 18a2 2 0 0 0 1.71 3h16.94a2 2 0 0 0 1.71-3L13.71 3.86a2 2 0 0 0-3.42 0z"/></>,
    sliders: <><line x1="4" y1="21" x2="4" y2="14"/><line x1="4" y1="10" x2="4" y2="3"/><line x1="12" y1="21" x2="12" y2="12"/><line x1="12" y1="8" x2="12" y2="3"/><line x1="20" y1="21" x2="20" y2="16"/><line x1="20" y1="12" x2="20" y2="3"/><line x1="1" y1="14" x2="7" y2="14"/><line x1="9" y1="8" x2="15" y2="8"/><line x1="17" y1="16" x2="23" y2="16"/></>,
    trash: <><polyline points="3 6 5 6 21 6"/><path d="M19 6v14a2 2 0 0 1-2 2H7a2 2 0 0 1-2-2V6m3 0V4a2 2 0 0 1 2-2h4a2 2 0 0 1 2 2v2"/></>,
  };
  return (
    <svg width={size} height={size} viewBox="0 0 24 24" fill="none"
         stroke="currentColor" strokeWidth="1.75" strokeLinecap="round" strokeLinejoin="round">
      {paths[name] || null}
    </svg>
  );
}

function AccountAvatar({ acc, size = 28 }) {
  const letters = acc.handle.replace('@','').split('.')[1] || acc.handle.slice(1,3);
  return (
    <span className="account-avatar" style={{ width:size, height:size, background: acc.color, fontSize: size*0.36 }}>
      {letters.slice(0,2).toUpperCase()}
      {size >= 24 && <span className={`status-dot ${acc.status}`}/>}
    </span>
  );
}

function ZodiacBadge({ z }) {
  const meta = window.SAJU.ZODIAC.find(x => x.key === z);
  if (!meta) return null;
  return (
    <span className="chip zodiac-chip">
      <span className="zodiac-ico">{meta.emoji}</span>
      <span>{meta.ko}</span>
    </span>
  );
}

function StatusFlow({ current }) {
  // order: pending -> approved -> scheduled -> published (+ failed/held branches)
  if (current === 'failed')  return <div className="flow"><span className="flow-step done">대기</span><span className="flow-arrow">→</span><span className="flow-step done">승인</span><span className="flow-arrow">→</span><span className="flow-step done">예약됨</span><span className="flow-arrow">→</span><span className="flow-step" style={{color:'var(--status-failed-fg)',borderColor:'var(--status-failed-dot)'}}>실패</span></div>;
  if (current === 'held')    return <div className="flow"><span className="flow-step done">대기</span><span className="flow-arrow">→</span><span className="flow-step" style={{color:'var(--status-held-fg)',borderColor:'var(--status-held-dot)'}}>보류</span></div>;
  const idx = STATUS_ORDER.indexOf(current);
  return (
    <div className="flow">
      {STATUS_ORDER.map((s, i) => (
        <React.Fragment key={s}>
          <span className={`flow-step ${i < idx ? 'done' : i === idx ? 'current' : 'pending'}`}>{STATUS_LABEL[s]}</span>
          {i < STATUS_ORDER.length - 1 && <span className="flow-arrow">→</span>}
        </React.Fragment>
      ))}
    </div>
  );
}

// Mini sparkline (SVG)
function Sparkline({ data, w = 80, h = 28, color = 'var(--accent)' }) {
  const max = Math.max(...data, 1);
  const min = Math.min(...data, 0);
  const range = max - min || 1;
  const points = data.map((v, i) => {
    const x = (i / (data.length - 1)) * w;
    const y = h - ((v - min) / range) * h;
    return `${x.toFixed(1)},${y.toFixed(1)}`;
  }).join(' ');
  return (
    <svg width={w} height={h} style={{ display: 'block' }}>
      <polyline points={points} fill="none" stroke={color} strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round"/>
    </svg>
  );
}

function Bars({ data, w = 80, h = 28, color = 'var(--accent)' }) {
  const max = Math.max(...data, 1);
  const bw = w / data.length - 2;
  return (
    <svg width={w} height={h} style={{display:'block'}}>
      {data.map((v, i) => {
        const bh = Math.max(2, (v / max) * h);
        return <rect key={i} x={i*(bw+2)} y={h-bh} width={bw} height={bh} fill={color} opacity={0.7 + (i/data.length)*0.3} rx="1"/>;
      })}
    </svg>
  );
}

// Export
Object.assign(window, { Badge, Icon, AccountAvatar, ZodiacBadge, StatusFlow, Sparkline, Bars, fmtTime, fmtRelative, STATUS_LABEL, STATUS_ORDER });
