// Shared widgets: icons, sparkline, mini-bar, stat card.

const I = {
  home: (p) => <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M3 11.5 12 4l9 7.5"/><path d="M5 10v10h14V10"/></svg>,
  server: (p) => <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round" {...p}><rect x="3" y="4" width="18" height="7" rx="2"/><rect x="3" y="13" width="18" height="7" rx="2"/><path d="M7 7.5h.01M7 16.5h.01"/></svg>,
  zap: (p) => <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M13 3 4 14h7l-1 7 9-11h-7z"/></svg>,
  users: (p) => <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round" {...p}><circle cx="9" cy="8" r="3.2"/><path d="M3 20c0-3.3 2.7-6 6-6s6 2.7 6 6"/><circle cx="17" cy="9" r="2.5"/><path d="M15 20c0-2.5 2-4.5 4.5-4.5"/></svg>,
  shield: (p) => <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M12 3 4 6v6c0 5 3.4 8.2 8 9 4.6-.8 8-4 8-9V6l-8-3z"/></svg>,
  list: (p) => <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M3 6h18M3 12h18M3 18h18"/></svg>,
  alert: (p) => <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="m12 3 10 18H2z"/><path d="M12 10v5M12 18h.01"/></svg>,
  plug: (p) => <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M9 3v6M15 3v6"/><path d="M7 9h10v4a5 5 0 0 1-10 0z"/><path d="M12 18v3"/></svg>,
  gear: (p) => <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round" {...p}><circle cx="12" cy="12" r="3"/><path d="M19.4 15a1.7 1.7 0 0 0 .3 1.8l.1.1a2 2 0 1 1-2.8 2.8l-.1-.1a1.7 1.7 0 0 0-1.8-.3 1.7 1.7 0 0 0-1 1.5V21a2 2 0 1 1-4 0v-.1a1.7 1.7 0 0 0-1-1.5 1.7 1.7 0 0 0-1.8.3l-.1.1a2 2 0 1 1-2.8-2.8l.1-.1a1.7 1.7 0 0 0 .3-1.8 1.7 1.7 0 0 0-1.5-1H3a2 2 0 1 1 0-4h.1a1.7 1.7 0 0 0 1.5-1 1.7 1.7 0 0 0-.3-1.8l-.1-.1a2 2 0 1 1 2.8-2.8l.1.1a1.7 1.7 0 0 0 1.8.3h0a1.7 1.7 0 0 0 1-1.5V3a2 2 0 1 1 4 0v.1a1.7 1.7 0 0 0 1 1.5 1.7 1.7 0 0 0 1.8-.3l.1-.1a2 2 0 1 1 2.8 2.8l-.1.1a1.7 1.7 0 0 0-.3 1.8v0a1.7 1.7 0 0 0 1.5 1H21a2 2 0 1 1 0 4h-.1a1.7 1.7 0 0 0-1.5 1z"/></svg>,
  search: (p) => <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round" {...p}><circle cx="11" cy="11" r="7"/><path d="m20 20-3.5-3.5"/></svg>,
  bell: (p) => <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M6 8a6 6 0 1 1 12 0c0 7 3 8 3 8H3s3-1 3-8"/><path d="M10 21a2 2 0 0 0 4 0"/></svg>,
  refresh: (p) => <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M21 12a9 9 0 1 1-3-6.7L21 8"/><path d="M21 3v5h-5"/></svg>,
  power: (p) => <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M12 3v9"/><path d="M5.6 6.6a8 8 0 1 0 12.8 0"/></svg>,
  arrow: (p) => <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M5 12h14M13 6l6 6-6 6"/></svg>,
  up: (p) => <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="m6 14 6-6 6 6"/></svg>,
  down: (p) => <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="m6 10 6 6 6-6"/></svg>,
  clock: (p) => <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round" {...p}><circle cx="12" cy="12" r="9"/><path d="M12 7v5l3 2"/></svg>,
  calendar: (p) => <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round" {...p}><rect x="3" y="5" width="18" height="16" rx="2"/><path d="M3 10h18M8 3v4M16 3v4"/></svg>,
  inbox: (p) => <svg viewBox="0 0 24 24" fill="none" stroke="currentColor" strokeWidth="1.7" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M3 13h5l2 3h4l2-3h5"/><path d="M3 13 5 5h14l2 8v6a2 2 0 0 1-2 2H5a2 2 0 0 1-2-2v-6z"/></svg>,
};

function Sparkline({ data, stroke = "var(--accent)", fill = true, height = 28 }) {
  const w = 120, h = height;
  const safe = (data || []).map((v) => Number(v) || 0);
  if (safe.length < 2) return <svg width={w} height={h} viewBox={`0 0 ${w} ${h}`}/>;
  const min = Math.min(...safe), max = Math.max(...safe);
  const span = max - min || 1;
  const pts = safe.map((v, i) => {
    const x = (i / (safe.length - 1)) * w;
    const y = h - ((v - min) / span) * (h - 4) - 2;
    return [x, y];
  });
  const d = pts.map((p, i) => `${i === 0 ? 'M' : 'L'}${p[0].toFixed(1)},${p[1].toFixed(1)}`).join(' ');
  const dFill = `${d} L${w},${h} L0,${h} Z`;
  return (
    <svg viewBox={`0 0 ${w} ${h}`} className="spark" preserveAspectRatio="none">
      {fill && (
        <path d={dFill} fill={`color-mix(in oklab, ${stroke} 18%, transparent)`} />
      )}
      <path d={d} fill="none" stroke={stroke} strokeWidth="1.5" strokeLinecap="round" strokeLinejoin="round" vectorEffect="non-scaling-stroke"/>
    </svg>
  );
}

function StatCard({ label, value, delta, deltaDir, spark, sparkColor }) {
  return (
    <div className="card stat">
      <div className="stat-label">{label}</div>
      <div className="stat-value">{value}</div>
      {(delta || spark) && (
        <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'flex-end', gap: 10 }}>
          {delta && (
            <div className={`stat-delta ${deltaDir || ''}`}>
              {deltaDir === 'up' && <I.up width="11" height="11"/>}
              {deltaDir === 'down' && <I.down width="11" height="11"/>}
              {delta}
            </div>
          )}
          {spark && (
            <div className="stat-spark" style={{ width: 110 }}>
              <Sparkline data={spark} stroke={sparkColor || "var(--accent)"} />
            </div>
          )}
        </div>
      )}
    </div>
  );
}

function MiniBars({ data, height = 110, color = "var(--accent)", highlightIdx = -1 }) {
  const safe = (data || []).map((v) => Number(v) || 0);
  const max = Math.max(1, ...safe);
  return (
    <div style={{ display: 'flex', alignItems: 'flex-end', gap: 4, height, paddingTop: 8 }}>
      {safe.map((v, i) => {
        const h = (v / max) * (height - 16);
        const isHi = i === highlightIdx;
        return (
          <div key={i} style={{ flex: 1, display: 'flex', flexDirection: 'column', alignItems: 'center', gap: 4 }}>
            <div style={{
              width: '100%',
              height: h,
              background: isHi ? color : `color-mix(in oklab, ${color} 55%, transparent)`,
              borderRadius: '3px 3px 0 0',
              transition: 'height 200ms',
            }}/>
          </div>
        );
      })}
    </div>
  );
}

function LineChart({ data, height = 220, color = "var(--accent)", labels = null, yTicks = 5 }) {
  const w = 800, h = height;
  const padL = 36, padR = 12, padT = 14, padB = 22;
  const innerW = w - padL - padR;
  const innerH = h - padT - padB;
  const min = 0;
  const max = (Math.max(0, ...(data || []).map((v) => Number(v) || 0)) || 1) * 1.1;
  const span = max - min || 1;
  const pts = data.map((v, i) => {
    const x = padL + (i / (data.length - 1)) * innerW;
    const y = padT + innerH - ((v - min) / span) * innerH;
    return [x, y];
  });
  const d = pts.map((p, i) => `${i === 0 ? 'M' : 'L'}${p[0].toFixed(1)},${p[1].toFixed(1)}`).join(' ');
  const dFill = `${d} L${padL + innerW},${padT + innerH} L${padL},${padT + innerH} Z`;
  const ticks = Array.from({ length: yTicks }, (_, i) => {
    const t = max - (i / (yTicks - 1)) * span;
    const y = padT + (i / (yTicks - 1)) * innerH;
    return { y, label: Math.round(t) };
  });
  return (
    <svg viewBox={`0 0 ${w} ${h}`} style={{ width: '100%', height: h, display: 'block' }}>
      {ticks.map((t, i) => (
        <g key={i}>
          <line x1={padL} x2={w - padR} y1={t.y} y2={t.y} stroke="var(--border)" strokeDasharray="2 3"/>
          <text x={padL - 6} y={t.y + 3} fill="var(--text-dim)" fontSize="10" textAnchor="end" fontFamily="var(--font-mono)">{t.label}</text>
        </g>
      ))}
      <path d={dFill} fill={`color-mix(in oklab, ${color} 16%, transparent)`}/>
      <path d={d} fill="none" stroke={color} strokeWidth="1.5" strokeLinejoin="round" strokeLinecap="round" vectorEffect="non-scaling-stroke"/>
      {pts.map((p, i) => i % 6 === 0 && (
        <circle key={i} cx={p[0]} cy={p[1]} r="2" fill={color} />
      ))}
      {labels && labels.map((l, i) => (
        <text key={i} x={padL + (i / (labels.length - 1)) * innerW} y={h - 6} fill="var(--text-dim)" fontSize="10" textAnchor="middle" fontFamily="var(--font-mono)">{l}</text>
      ))}
    </svg>
  );
}

function Card({ title, sub, action, children, padding, className = '' }) {
  return (
    <div className={`card ${className}`} style={padding != null ? { padding } : undefined}>
      {(title || action) && (
        <div className="card-head">
          <div>
            {title && <div className="card-title">{title}</div>}
            {sub && <div className="card-sub">{sub}</div>}
          </div>
          {action}
        </div>
      )}
      {children}
    </div>
  );
}

function GuildAvatar({ name, color, icon }) {
  const isUrl = typeof icon === 'string' && /^https?:\/\//.test(icon);
  if (isUrl) {
    return (
      <div className="guild-avatar" style={{ background: color, padding: 0, overflow: 'hidden' }}>
        <img
          src={icon}
          alt=""
          referrerPolicy="no-referrer"
          onError={(e) => {
            // ถ้ารูปโหลดไม่ได้ → fallback เป็นตัวอักษรย่อ
            e.currentTarget.style.display = 'none';
            const p = e.currentTarget.parentElement;
            if (p && !p.dataset.fb) { p.dataset.fb = '1'; p.textContent = (name || '?').slice(0, 2).toUpperCase(); }
          }}
          style={{ width: '100%', height: '100%', objectFit: 'cover', display: 'block' }}
        />
      </div>
    );
  }
  return (
    <div className="guild-avatar" style={{ background: color }}>{icon || (name || '?').slice(0, 2).toUpperCase()}</div>
  );
}

function Switch({ on, onChange }) {
  return <div className="switch" data-on={on ? 'true' : 'false'} onClick={() => onChange(!on)} role="switch" aria-checked={on}/>;
}

Object.assign(window, { I, Sparkline, StatCard, MiniBars, LineChart, Card, GuildAvatar, Switch });
