// Shared small primitives for the admin UI kit.
// Status tone + tiny SVG icons + labels matching the codebase.

const STATUS_LABELS = {
  queued: 'Inbox', running: 'Running', waiting_human: 'Waiting',
  waiting_subtasks: 'Subtasks', retry: 'Retry', succeeded: 'Done',
  failed: 'Failed', cancelled: 'Cancelled',
};

const STATUS_TONE = {
  running:          { bg: '#dcfce7', fg: '#166534' },
  waiting_human:    { bg: '#fef9c3', fg: '#854d0e' },
  waiting_subtasks: { bg: '#e0e7ff', fg: '#3730a3' },
  failed:           { bg: '#fee2e2', fg: '#b91c1c' },
  succeeded:        { bg: '#dbeafe', fg: '#1e40af' },
  retry:            { bg: '#fef3c7', fg: '#92400e' },
  queued:           { bg: '#e2e8f0', fg: '#475569' },
  cancelled:        { bg: '#e2e8f0', fg: '#475569' },
};

function StatusBadge({ status, small }) {
  const tone = STATUS_TONE[status] || STATUS_TONE.queued;
  const label = STATUS_LABELS[status] || status;
  const style = {
    background: tone.bg, color: tone.fg,
    fontSize: small ? 10 : 11, fontWeight: 700,
    padding: small ? '1px 8px' : '2px 10px', borderRadius: 9999,
    display: 'inline-flex', alignItems: 'center', whiteSpace: 'nowrap',
  };
  return <span style={style}>{label}</span>;
}

function StatChip({ label, value, color }) {
  return (
    <div style={{
      background: '#fff', border: '1px solid #e2e8f0', borderRadius: 12,
      padding: '8px 12px', boxShadow: '0 1px 2px 0 rgb(0 0 0 / 0.05)',
      minWidth: 0, flex: '1 1 0', minWidth: 80,
    }}>
      <div style={{ fontSize: 10, fontWeight: 700, color: '#64748b', letterSpacing: '.06em', textTransform: 'uppercase', whiteSpace: 'nowrap' }}>{label}</div>
      <div style={{
        fontSize: 15, fontWeight: 800, color: color || '#0f172a', marginTop: 2,
        overflow: 'hidden', textOverflow: 'ellipsis', whiteSpace: 'nowrap',
      }}>{value}</div>
    </div>
  );
}

function Spinner() {
  return <div style={{
    width: 16, height: 16, border: '2px solid #e2e8f0', borderTopColor: '#2563eb',
    borderRadius: '9999px', animation: 'ao-spin 1s linear infinite', display: 'inline-block',
  }} />;
}

function PulseDot() {
  return <span style={{
    display: 'inline-block', width: 8, height: 8, background: '#3b82f6',
    borderRadius: 9999, animation: 'ao-pulse 1.2s ease-in-out infinite',
  }} />;
}

function IconSearch(props) {
  return <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...props}><path d="M21 21l-6-6m2-5a7 7 0 11-14 0 7 7 0 0114 0z"/></svg>;
}
function IconAttach(props) {
  return <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...props}><path d="M21.44 11.05l-9.19 9.19a6 6 0 01-8.49-8.49l9.19-9.19a4 4 0 015.66 5.66l-9.2 9.19a2 2 0 01-2.83-2.83l8.49-8.48"/></svg>;
}
function IconClose(props) {
  return <svg viewBox="0 0 16 16" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" {...props}><path d="M4 4l8 8M12 4l-8 8"/></svg>;
}

// ---- State primitives: loading / empty / error ----

function SkeletonLine({ width = '100%', height = 10, style }) {
  return <div style={{
    width, height, borderRadius: 6,
    background: 'linear-gradient(90deg, #f1f5f9 0%, #e2e8f0 50%, #f1f5f9 100%)',
    backgroundSize: '200% 100%',
    animation: 'ao-shimmer 1.4s ease-in-out infinite',
    ...style,
  }} />;
}

function SkeletonCard({ lines = 2 }) {
  return (
    <div style={{
      padding: '10px 12px', borderRadius: 12, border: '1px solid #e2e8f0',
      background: '#fff', display: 'flex', flexDirection: 'column', gap: 6,
    }}>
      <div style={{ display: 'flex', alignItems: 'center', justifyContent: 'space-between', gap: 8 }}>
        <SkeletonLine width="60%" height={12} />
        <SkeletonLine width={44} height={14} style={{ borderRadius: 9999 }} />
      </div>
      {Array.from({ length: lines }).map((_, i) => (
        <SkeletonLine key={i} width={i === lines - 1 ? '40%' : '90%'} height={9} />
      ))}
    </div>
  );
}

function SkeletonList({ count = 5, lines = 2 }) {
  return (
    <div style={{ display: 'flex', flexDirection: 'column', gap: 6 }}>
      {Array.from({ length: count }).map((_, i) => <SkeletonCard key={i} lines={lines} />)}
    </div>
  );
}

function EmptyState({ icon, title, hint, action, compact }) {
  return (
    <div style={{
      display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center',
      textAlign: 'center', padding: compact ? '24px 16px' : '48px 24px', gap: 8,
      color: '#64748b',
    }}>
      {icon && <div style={{
        width: 40, height: 40, borderRadius: 9999, background: '#f1f5f9',
        display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
        color: '#94a3b8', marginBottom: 4,
      }}>{icon}</div>}
      {title && <div style={{ fontSize: 13, fontWeight: 700, color: '#334155' }}>{title}</div>}
      {hint && <div style={{ fontSize: 12, color: '#64748b', maxWidth: 280, lineHeight: 1.5 }}>{hint}</div>}
      {action && <div style={{ marginTop: 8 }}>{action}</div>}
    </div>
  );
}

function ErrorState({ title = '読み込みに失敗しました', hint, onRetry, compact }) {
  return (
    <div style={{
      display: 'flex', flexDirection: 'column', alignItems: 'center', justifyContent: 'center',
      textAlign: 'center', padding: compact ? '24px 16px' : '40px 24px', gap: 8,
    }}>
      <div style={{
        width: 40, height: 40, borderRadius: 9999, background: '#fee2e2',
        display: 'inline-flex', alignItems: 'center', justifyContent: 'center',
        color: '#b91c1c', marginBottom: 4,
      }}>
        <svg width="20" height="20" viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round"><path d="M12 9v4m0 4h.01M10.29 3.86L1.82 18a2 2 0 001.71 3h16.94a2 2 0 001.71-3L13.71 3.86a2 2 0 00-3.42 0z"/></svg>
      </div>
      <div style={{ fontSize: 13, fontWeight: 700, color: '#b91c1c' }}>{title}</div>
      {hint && <div style={{ fontSize: 12, color: '#64748b', maxWidth: 320, lineHeight: 1.5 }}>{hint}</div>}
      {onRetry && (
        <button onClick={onRetry} style={{
          marginTop: 4, padding: '6px 14px', borderRadius: 8, fontSize: 12, fontWeight: 700,
          background: '#fff', border: '1px solid #e2e8f0', color: '#334155',
          cursor: 'pointer', fontFamily: 'inherit',
        }}>再試行</button>
      )}
    </div>
  );
}

function relativeTime(ms) {
  const mins = Math.floor((Date.now() - ms) / 60000);
  if (mins < 1) return 'たった今';
  if (mins < 60) return `${mins}分前`;
  const hrs = Math.floor(mins / 60);
  if (hrs < 24) return `${hrs}時間前`;
  return `${Math.floor(hrs / 24)}日前`;
}

Object.assign(window, {
  STATUS_LABELS, STATUS_TONE,
  StatusBadge, StatChip, Spinner, PulseDot,
  SkeletonLine, SkeletonCard, SkeletonList, EmptyState, ErrorState,
  IconSearch, IconAttach, IconClose, relativeTime,
});
