/**
 * VB Design System — React Components (CDN/Babel前提、.jsx)
 *
 * 使い方（HTMLに直接読込むタイプのプロジェクト向け）:
 *   <script type="text/babel" src="/shared/design-system/components/index.jsx"></script>
 *   window.IDDS.TierDot, window.IDDS.SectionHead 等でアクセス可能
 *
 * モダンビルド（Vite等）での使い方:
 *   named exports に変更して import すること
 */
(function (global) {
  const { useState, useEffect, useMemo, useCallback, useRef } = React;

  /* ============================================
     Dots & Badges
     ============================================ */
  function TierDot({ tier, size = 8 }) {
    if (!tier) return null;
    return (
      <span className={`tier-${tier}`}
        style={{ display: 'inline-block', width: size, height: size, borderRadius: '50%' }}
        aria-label={`tier-${tier}`} />
    );
  }

  function ConfidenceBadge({ level }) {
    // level: 'high'|'mid'|'low'|'ref'
    const labels = { high: '高', mid: '中', low: '低', ref: '参考' };
    return (
      <span className="inline-flex items-center gap-1">
        <span className={`conf-${level}`} style={{ display: 'inline-block', width: 6, height: 6, borderRadius: '50%' }} />
        <span style={{ fontSize: 10, color: 'var(--ink-mute)' }}>{labels[level] || level}</span>
      </span>
    );
  }

  /* ============================================
     Section Head
     ============================================ */
  function SectionHead({ num, jp, en }) {
    return (
      <div className="sec-head">
        {num && <span className="sec-num">{num}</span>}
        <span className="sec-jp">{jp}</span>
        {en && <span className="sec-en smcp">{en}</span>}
      </div>
    );
  }

  /* ============================================
     KPI Card
     ============================================ */
  function KpiCard({ label, en, value, suffix, foot, compare }) {
    return (
      <div className="kpi-card hair-r md:last:border-r-0">
        <div className="flex flex-col gap-1">
          <div className="serif" style={{ fontSize: 11, color: 'var(--ink-mute)', letterSpacing: '0.08em' }}>{label}</div>
          {en && <div className="ga-italic smcp" style={{ fontSize: 9, color: 'var(--ink-faint)' }}>{en}</div>}
          <div className="flex items-baseline flex-wrap gap-1.5 mt-1">
            <span className="kpi-value ga-italic" style={{ fontSize: 34, lineHeight: 1, color: 'var(--ink)' }}>{value}</span>
            {suffix && <span className="kpi-suffix ga-italic" style={{ fontSize: 13, color: 'var(--ink-mute)' }}>{suffix}</span>}
          </div>
          {foot && <div className="kpi-foot ga-italic" style={{ fontSize: 10, color: 'var(--ink-faint)' }}>{foot}</div>}
          {compare && (
            <div className="ga-italic" style={{ fontSize: 10, color: compare.positive ? 'var(--positive)' : 'var(--negative)' }}>
              {compare.positive ? '▲' : '▼'} {compare.pct != null ? Math.abs(compare.pct).toFixed(1) + '%' : compare.value}
            </div>
          )}
        </div>
      </div>
    );
  }

  /* ============================================
     Form Controls
     ============================================ */
  function SelectFilter({ label, value, onChange, options, counts, allLabel = 'すべて', colorDots }) {
    return (
      <div className="mb-4">
        {label && <div className="sb-section">{label}</div>}
        <select className="sb-select" value={value || ''} onChange={e => onChange(e.target.value)}>
          <option value="">{allLabel}</option>
          {(options || []).map(o => {
            const v = typeof o === 'string' ? o : o.value;
            const l = typeof o === 'string' ? o : o.label;
            const c = counts && counts[v] ? ` (${counts[v]})` : '';
            return <option key={v} value={v}>{l}{c}</option>;
          })}
        </select>
      </div>
    );
  }

  function SliderFilter({ label, value, onChange, suffix, min, max, step, displayFn }) {
    const numVal = value ? parseFloat(value) : min;
    const display = displayFn ? displayFn(numVal) : numVal;
    const isActive = value !== '' && value != null && parseFloat(value) !== min;
    return (
      <div className="mb-4">
        <div className="sb-section flex items-baseline justify-between">
          <span>{label}</span>
          {isActive && <span className="ga-italic" style={{ fontSize: 11, color: 'var(--ink)' }}>{display}{suffix}</span>}
        </div>
        <input type="range" className="sb-slider" style={{ width: '100%' }}
          min={min} max={max} step={step} value={numVal}
          onChange={e => {
            const v = parseFloat(e.target.value);
            onChange(v <= min ? '' : String(v));
          }} />
        <div className="flex justify-between ga-italic" style={{ fontSize: 9, color: 'var(--ink-faint)', marginTop: 2 }}>
          <span>{displayFn ? displayFn(min) : min}{suffix}</span>
          <span>{displayFn ? displayFn(max) : max}{suffix}</span>
        </div>
      </div>
    );
  }

  function ToggleRow({ label, checked, onChange }) {
    return (
      <div className={`sw-row ${checked ? 'active' : ''}`} onClick={() => onChange(!checked)}>
        <span className="sw-label">{label}</span>
        <span className={`sw-track ${checked ? 'on' : ''}`}><span className="sw-knob"></span></span>
      </div>
    );
  }

  /* ============================================
     Password Gate
     ============================================ */
  function PasswordGate({ children, password, storageKey = 'vb_ds_auth', title = 'Members Only' }) {
    const [authenticated, setAuthenticated] = useState(() => {
      try { return localStorage.getItem(storageKey) === 'true' || sessionStorage.getItem(storageKey) === 'true'; }
      catch (e) { return false; }
    });
    const [input, setInput] = useState('');
    const [error, setError] = useState('');
    const handleSubmit = (e) => {
      e.preventDefault();
      if (input === password) {
        try { localStorage.setItem(storageKey, 'true'); } catch (e) {}
        try { sessionStorage.setItem(storageKey, 'true'); } catch (e) {}
        setAuthenticated(true);
      } else {
        setError('パスワードが正しくありません');
        setInput('');
      }
    };
    if (authenticated) return children;
    return (
      <div className="min-h-screen flex items-center justify-center bg-paper">
        <div className="hair-strong-all bg-paper p-10 w-full max-w-sm">
          <div className="text-center mb-6">
            <div className="ga-italic smcp" style={{ fontSize: 11, color: 'var(--ink-mute)', marginBottom: 4 }}>The Valuebooks</div>
            <h1 className="serif" style={{ fontSize: 22, fontWeight: 600, color: 'var(--ink)' }}>{title}</h1>
          </div>
          <form onSubmit={handleSubmit} action="#">
            <input type="text" name="username" defaultValue="valuebooks" autoComplete="username" className="hidden" />
            <input type="password" name="password" value={input}
              onChange={e => { setInput(e.target.value); setError(''); }}
              placeholder="Password" autoFocus autoComplete="current-password"
              className="sb-input text-center" style={{ padding: '10px 12px', fontSize: 13 }} />
            {error && <p className="ga-italic" style={{ color: 'var(--accent)', fontSize: 11, marginTop: 8, textAlign: 'center' }}>{error}</p>}
            <button type="submit" className="w-full mt-4"
              style={{ background: 'var(--ink)', color: 'var(--paper)', padding: '10px', fontFamily: 'var(--font-serif)', fontSize: 13, letterSpacing: '0.08em', cursor: 'pointer', border: 'none' }}>
              Enter
            </button>
          </form>
        </div>
      </div>
    );
  }

  /* ============================================
     Expose
     ============================================ */
  global.IDDS = {
    TierDot, ConfidenceBadge,
    SectionHead,
    KpiCard,
    SelectFilter, SliderFilter, ToggleRow,
    PasswordGate,
  };
})(typeof window !== 'undefined' ? window : globalThis);
