// atoms.jsx — primitive shared components

// Avatar
function Avatar({ user, size = 'sm', ring = false }) {
  const u = typeof user === 'string' ? USER_BY_ID[user] : user;
  if (!u) return null;
  return (
    <div className={`av ${size}`} style={{
      background: `linear-gradient(135deg, ${u.color}, color-mix(in oklab, ${u.color} 60%, #fff))`,
      boxShadow: ring ? `0 0 0 2px var(--bg-card), 0 0 0 4px ${u.color}` : undefined,
    }}>{u.initials}</div>
  );
}

function AvStack({ users, max = 3, size = 'sm' }) {
  const list = (users || []).slice(0, max);
  const extra = (users || []).length - list.length;
  return (
    <div className="av-stack">
      {list.map((id, i) => <Avatar key={id+i} user={id} size={size} />)}
      {extra > 0 && (
        <div className={`av ${size}`} style={{ background: 'var(--bg-elev)', color: 'var(--text-secondary)', border: '2px solid var(--bg-card)' }}>+{extra}</div>
      )}
    </div>
  );
}

// Zone chip
function ZoneChip({ zone, sm = false }) {
  const z = typeof zone === 'string' ? ZONE_BY_ID[zone] : zone;
  if (!z) return null;
  return (
    <span className={`chip ${z.cls}`} style={{ fontSize: sm ? 10.5 : undefined, padding: sm ? '2px 7px' : undefined }}>
      <span className="glyph">{z.icon}</span>{z.name}
    </span>
  );
}

// Icons — functional components that accept props
const __iconBase = (props, paths) => (
  <svg viewBox="0 0 24 24" width="18" height="18" fill="none" stroke="currentColor"
       strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...props}
       className={'icon ' + (props.className || '')}>{paths}</svg>
);
const Icon = {
  dashboard: (p={}) => __iconBase(p, <g><rect x="3" y="3" width="7" height="9" rx="1.5"/><rect x="14" y="3" width="7" height="5" rx="1.5"/><rect x="14" y="12" width="7" height="9" rx="1.5"/><rect x="3" y="16" width="7" height="5" rx="1.5"/></g>),
  map:       (p={}) => __iconBase(p, <g><rect x="3" y="4" width="6" height="16" rx="1.5"/><rect x="10" y="4" width="6" height="10" rx="1.5"/><rect x="17" y="4" width="4" height="6" rx="1.5"/></g>),
  wheel:     (p={}) => __iconBase(p, <g><circle cx="12" cy="12" r="9"/><path d="M12 3v18M3 12h18M5 5l14 14M19 5L5 19"/></g>),
  habits:    (p={}) => __iconBase(p, <g><path d="M3 13v3a2 2 0 002 2h14a2 2 0 002-2V8a2 2 0 00-2-2H5a2 2 0 00-2 2v0"/><path d="M7 10l2 2 4-4"/><path d="M3 8l3-3 3 3"/></g>),
  matrix:    (p={}) => __iconBase(p, <g><rect x="3" y="3" width="8" height="8" rx="1.5"/><rect x="13" y="3" width="8" height="8" rx="1.5"/><rect x="3" y="13" width="8" height="8" rx="1.5"/><rect x="13" y="13" width="8" height="8" rx="1.5"/></g>),
  profile:   (p={}) => __iconBase(p, <g><circle cx="12" cy="8" r="4"/><path d="M3 21c1.5-4 5-6 9-6s7.5 2 9 6"/></g>),
  team:      (p={}) => __iconBase(p, <g><circle cx="9" cy="8" r="3.5"/><path d="M3 20c1-3 3-5 6-5s5 2 6 5"/><circle cx="17" cy="7" r="2.5"/><path d="M16 20c.6-2 1.7-3.3 3-4"/></g>),
  bell:      (p={}) => __iconBase(p, <g><path d="M6 9a6 6 0 0112 0c0 6 2.5 6 2.5 8h-17C4 15 6 15 6 9z"/><path d="M10 19a2 2 0 004 0"/></g>),
  search:    (p={}) => __iconBase({width: 14, height: 14, ...p}, <g><circle cx="11" cy="11" r="7"/><path d="M16.5 16.5L21 21"/></g>),
  plus:      (p={}) => __iconBase({width: 16, height: 16, strokeWidth: 2.5, ...p}, <path d="M12 5v14M5 12h14"/>),
  fire:      (p={}) => <svg viewBox="0 0 24 24" width="14" height="14" fill="currentColor" {...p}><path d="M12.5 2c.4 4 4 5 4 10a4.5 4.5 0 11-9 0c0-2 1-3 1-5 2 1 2.5 2 2.5 4 1-2 1.5-5 1.5-9z"/></svg>,
  check:     (p={}) => <svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" strokeWidth="3" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M5 12l4 4 10-10"/></svg>,
  star:      (p={}) => <svg viewBox="0 0 24 24" width="14" height="14" fill="currentColor" {...p}><path d="M12 2l3 7h7l-5.5 4.5L18 21l-6-4-6 4 1.5-7.5L2 9h7z"/></svg>,
  lock:      (p={}) => <svg viewBox="0 0 24 24" width="13" height="13" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><rect x="4" y="11" width="16" height="10" rx="2"/><path d="M8 11V7a4 4 0 018 0v4"/></svg>,
  arrow:     (p={}) => <svg viewBox="0 0 24 24" width="14" height="14" fill="none" stroke="currentColor" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round" {...p}><path d="M5 12h14M13 6l6 6-6 6"/></svg>,
};

// Progress ring
function ProgressRing({ value, size = 64, stroke = 6, color, label, sub }) {
  const r = (size - stroke) / 2;
  const c = 2 * Math.PI * r;
  const off = c - (Math.max(0, Math.min(1, value)) * c);
  return (
    <div style={{ width: size, height: size, position: 'relative' }}>
      <svg width={size} height={size} style={{ transform: 'rotate(-90deg)' }}>
        <circle cx={size/2} cy={size/2} r={r} stroke="var(--border)" strokeWidth={stroke} fill="none" />
        <circle cx={size/2} cy={size/2} r={r} stroke={color || 'var(--accent)'} strokeWidth={stroke} fill="none"
          strokeDasharray={c} strokeDashoffset={off} strokeLinecap="round"
          style={{ transition: 'stroke-dashoffset 360ms cubic-bezier(0.34, 1.56, 0.64, 1)',
                   filter: 'drop-shadow(0 0 calc(8px * var(--glow-mult)) ' + (color || 'var(--accent)') + ')' }}
        />
      </svg>
      <div style={{
        position: 'absolute', inset: 0, display: 'grid', placeContent: 'center',
        textAlign: 'center', lineHeight: 1.1,
      }}>
        <div style={{ fontFamily: 'var(--font-mono)', fontWeight: 700, fontSize: size < 60 ? 13 : 15 }}>
          {label != null ? label : `${Math.round(value * 100)}%`}
        </div>
        {sub && <div style={{ fontSize: 9, color: 'var(--text-tertiary)', fontFamily: 'var(--font-mono)', marginTop: 2 }}>{sub}</div>}
      </div>
    </div>
  );
}

// XP Bar
function XPBar({ user = ME, big = false }) {
  const lvl = user.level;
  const cur = user.xp;
  const baseXp = PROGRESSION.thresholds[lvl] || 0;
  const nextXp = PROGRESSION.thresholds[lvl + 1] || (cur + 500);
  const pct = Math.max(0, Math.min(1, (cur - baseXp) / (nextXp - baseXp)));
  return (
    <div>
      <div className="spread mb-2">
        <div className="row" style={{ gap: 8 }}>
          <span style={{ fontFamily: 'var(--font-display)', fontWeight: 700, fontSize: big ? 16 : 13 }}>
            {PROGRESSION.names[lvl]}
          </span>
          <span className="lvl-pill">LVL {lvl}</span>
        </div>
        <div className="mono dim" style={{ fontSize: big ? 13 : 11.5 }}>
          {cur.toLocaleString('ru')} / {nextXp.toLocaleString('ru')} XP
        </div>
      </div>
      <div className="xp-bar" style={{ height: big ? 10 : 7 }}>
        <i style={{ width: `${pct * 100}%` }} />
      </div>
      <div className="spread mt-2" style={{ fontSize: 11, color: 'var(--text-tertiary)' }}>
        <span className="mono">+{nextXp - cur} XP до следующего</span>
        <span className="mono">{Math.round(pct * 100)}%</span>
      </div>
    </div>
  );
}

// Badge cell
function BadgeCell({ badge, large = false }) {
  return (
    <div className={`badge-cell rarity-${badge.rarity} ${badge.earned ? '' : 'locked'}`}
         style={{ padding: large ? '16px 12px' : undefined }}
         title={badge.desc}>
      <div className="glyph" style={{ width: large ? 64 : 52, height: large ? 64 : 52, fontSize: large ? 28 : 22 }}>
        {badge.earned ? badge.icon : <Icon.lock />}
      </div>
      <div className="nm">{badge.name}</div>
      <div className="desc">
        {badge.earned ? (badge.date || 'получено') : (badge.progress || badge.desc)}
      </div>
    </div>
  );
}

// Wish card (large, kanban)
function WishCard({ wish, draggable = true, onClick, onDragStart, dragging = false }) {
  const z = ZONE_BY_ID[wish.zone];
  const pct = wish.steps_total ? wish.steps_done / wish.steps_total : 0;
  return (
    <div className={`wish ${z.cls} ${dragging ? 'dragging' : ''}`}
         draggable={draggable}
         onDragStart={onDragStart}
         onClick={onClick}>
      <div className="cover">{wish.cover}</div>
      <div>
        <div className="title">{wish.title}</div>
        <div className="meta mt-2">
          <ZoneChip zone={z} sm />
          {wish.due && <span className="due">📅 {wish.due}</span>}
          {wish.shared && wish.shared.length > 1 && (
            <span className="due"><Icon.team style={{ width: 12, height: 12 }} /> {wish.shared.length}</span>
          )}
        </div>
      </div>
      <div className="progress" title={`${wish.steps_done}/${wish.steps_total}`}>
        <i style={{ width: `${pct * 100}%` }} />
      </div>
      <div className="wish-foot">
        <span className="step-count"><b>{wish.steps_done}</b>/{wish.steps_total} шагов</span>
        <AvStack users={wish.shared} max={3} />
      </div>
    </div>
  );
}

// Goal step (checkbox row)
function GoalStep({ step, onToggle }) {
  return (
    <div className={`step ${step.done ? 'done' : ''}`} onClick={() => onToggle?.(step.id)}>
      <div className="box">{step.done && <Icon.check />}</div>
      <div className="text">{step.title}</div>
      {step.assignee && <Avatar user={step.assignee} size="sm" />}
      <span className={`due ${step.overdue ? 'overdue' : ''}`}>{step.due}</span>
    </div>
  );
}

// Heatmap (52 weeks × 7 days)
function Heatmap({ data, zone, compact = false }) {
  const z = ZONE_BY_ID[zone] || { cls: '', color: 'var(--accent)' };
  return (
    <div className={`heatmap ${z.cls} ${compact ? 'compact' : ''}`}>
      {data.map((lvl, i) => (
        <div key={i} className="cell" style={{ '--l': lvl / 4 }} title={`день ${i+1} · уровень ${lvl}`} />
      ))}
    </div>
  );
}

// Radar / LifeWheel — with stagger mount animation
function LifeWheel({ size = 480, current, target, interactive = false, onChange }) {
  const cx = size / 2, cy = size / 2;
  const padding = 50;
  const maxR = (size - padding * 2) / 2;
  const n = ZONES.length;

  // mount animation: each axis appears in stagger
  const [mountT, setMountT] = React.useState(0);
  React.useEffect(() => {
    let raf;
    const start = performance.now();
    const duration = 900;
    const tick = (now) => {
      const t = Math.min(1, (now - start) / duration);
      // easeOutBack
      const eased = 1 + 2.7 * Math.pow(t - 1, 3) + 1.7 * Math.pow(t - 1, 2);
      setMountT(eased);
      if (t < 1) raf = requestAnimationFrame(tick);
    };
    raf = requestAnimationFrame(tick);
    return () => cancelAnimationFrame(raf);
  }, []);

  const pt = (i, v) => {
    const angle = (Math.PI * 2 * i) / n - Math.PI / 2;
    // stagger: each axis reaches full at progressive points
    const axisDelay = i / n * 0.6; // 0..0.6
    const axisT = Math.max(0, Math.min(1, (mountT - axisDelay) / (1 - axisDelay)));
    const r = (v / 10) * maxR * axisT;
    return [cx + r * Math.cos(angle), cy + r * Math.sin(angle)];
  };
  const ptLabel = (i) => {
    const angle = (Math.PI * 2 * i) / n - Math.PI / 2;
    const r = maxR + 18;
    return [cx + r * Math.cos(angle), cy + r * Math.sin(angle)];
  };

  const currentPath = ZONES.map((z, i) => pt(i, current[z.id])).map(([x, y], i) => `${i === 0 ? 'M' : 'L'} ${x} ${y}`).join(' ') + ' Z';
  const targetPath  = ZONES.map((z, i) => pt(i, target[z.id])).map(([x, y], i) => `${i === 0 ? 'M' : 'L'} ${x} ${y}`).join(' ') + ' Z';

  return (
    <svg className="radar" viewBox={`0 0 ${size} ${size}`} width={size} height={size}>
      {/* Concentric rings */}
      {[2, 4, 6, 8, 10].map((step) => (
        <circle key={step} className={step === 10 ? 'ring' : 'ring faint'}
                cx={cx} cy={cy} r={(step / 10) * maxR} />
      ))}
      {/* Axes + labels */}
      {ZONES.map((z, i) => {
        const [ex, ey] = pt(i, 10);
        const [lx, ly] = ptLabel(i);
        return (
          <g key={z.id}>
            <line className="axis" x1={cx} y1={cy} x2={ex} y2={ey} />
            <text x={lx} y={ly} textAnchor="middle" dominantBaseline="middle" style={{ fill: z.color, fontWeight: 600, fontSize: 11 }}>
              {z.icon} {z.name}
            </text>
          </g>
        );
      })}
      {/* Target (dashed) */}
      <path className="target" d={targetPath} />
      {/* Current */}
      <path className="current" d={currentPath} />
      {/* Points */}
      {ZONES.map((z, i) => {
        const [x, y] = pt(i, current[z.id]);
        return (
          <g key={z.id}>
            <circle className="pt" cx={x} cy={y} r={5} style={{ fill: z.color, filter: 'drop-shadow(0 0 calc(8px * var(--glow-mult)) ' + z.color + ')' }} />
            <text x={x} y={y - 12} textAnchor="middle" style={{ fill: z.color, fontFamily: 'var(--font-mono)', fontWeight: 700, fontSize: 11 }}>
              {current[z.id]}
            </text>
          </g>
        );
      })}
    </svg>
  );
}

// Toast
function Toast({ icon, title, sub, xp }) {
  return (
    <div className="toast">
      <div style={{ fontSize: 22 }}>{icon}</div>
      <div style={{ flex: 1 }}>
        <div style={{ fontWeight: 600 }}>{title}</div>
        {sub && <div style={{ fontSize: 11.5, color: 'var(--text-tertiary)' }}>{sub}</div>}
      </div>
      {xp != null && <div className="xp">+{xp} XP</div>}
    </div>
  );
}

Object.assign(window, {
  Avatar, AvStack, ZoneChip, Icon,
  ProgressRing, XPBar, BadgeCell, WishCard, GoalStep, Heatmap, LifeWheel, Toast,
});
