/* ===== 可视化组件 ===== */

/* 中文数字工具 */
const CN = ['零','一','二','三','四','五','六','七','八','九','十'];
function cnNum(n) {
  if (n <= 10) return CN[n];
  if (n < 20) return '十' + (n % 10 === 0 ? '' : CN[n % 10]);
  const t = Math.floor(n / 10), o = n % 10;
  return CN[t] + '十' + (o === 0 ? '' : CN[o]);
}
function koujue(a, b) {
  const lo = Math.min(a, b), hi = Math.max(a, b), p = a * b;
  return CN[lo] + CN[hi] + (p < 10 ? '得' : '') + cnNum(p);
}
window.cnNum = cnNum; window.koujue = koujue; window.CN = CN;

/* ---- 单颗糖豆 ---- */
function Bead({ color, size = 38, x, empty, removed, delay = 0 }) {
  const base = {
    width: size, height: size, borderRadius: '50%',
    display: 'flex', alignItems: 'center', justifyContent: 'center',
    transition: 'all .3s', position: 'relative',
  };
  if (empty) {
    return <div style={{ ...base, background: 'rgba(74,59,107,.06)',
      border: '2px dashed rgba(74,59,107,.18)' }} />;
  }
  return (
    <div style={{
      ...base,
      background: color,
      boxShadow: `inset -4px -5px 0 rgba(0,0,0,.12), inset 4px 4px 0 rgba(255,255,255,.4)`,
      opacity: removed ? 0.28 : 1,
      filter: removed ? 'grayscale(.6)' : 'none',
    }}>
      {removed && <span style={{ fontSize: size * 0.7, color: '#fff', fontWeight: 900,
        textShadow: '0 1px 0 rgba(0,0,0,.2)' }}>✕</span>}
    </div>
  );
}

/* ---- 十格框(2行×5,以5为基数) ----
   接收一个 cells 数组,每个元素: null=空, {color, removed} */
function Frame({ cells, size = 38 }) {
  return (
    <div style={{
      display: 'grid', gridTemplateColumns: `repeat(5, ${size}px)`,
      gridTemplateRows: `repeat(2, ${size}px)`, gap: 8, padding: 10,
      background: '#fff', borderRadius: 18,
      boxShadow: 'inset 0 0 0 3px rgba(74,59,107,.10)',
      position: 'relative',
    }}>
      {/* 第5格后的分隔提示线(5为基数) */}
      <div style={{ position: 'absolute', left: `calc(${size * 2.5}px + ${10 + 8 * 2.5}px)`,
        top: 6, bottom: 6, width: 3, borderRadius: 3, background: 'rgba(255,201,60,.55)' }} />
      {cells.map((c, i) => (
        <Bead key={i} size={size} empty={!c} color={c && c.color}
          removed={c && c.removed} delay={i * 45} />
      ))}
    </div>
  );
}

/* 把数字 n 拆成十格框组(每框10),按 a/b 上色 */
function buildCells(a, b, removedFrom) {
  const total = a + b;
  const frames = Math.max(1, Math.ceil(Math.max(total, 1) / 10));
  const all = [];
  for (let i = 0; i < frames * 10; i++) {
    if (i < a) all.push({ color: 'var(--pink)', removed: false });
    else if (i < a + b) all.push({ color: 'var(--blue)', removed: false });
    else all.push(null);
  }
  if (removedFrom != null) {
    // 从末尾标记 removedFrom 个为“拿走”
    let cnt = removedFrom, i = a - 1;
    while (cnt > 0 && i >= 0) { all[i].removed = true; i--; cnt--; }
  }
  const out = [];
  for (let f = 0; f < frames; f++) out.push(all.slice(f * 10, f * 10 + 10));
  return out;
}

/* 加法可视化:a(粉) + b(蓝) */
function AddViz({ a, b }) {
  const frames = buildCells(a, b);
  return (
    <div style={{ display: 'flex', gap: 22, flexWrap: 'wrap', justifyContent: 'center' }}>
      {frames.map((cells, i) => <Frame key={i} cells={cells} />)}
    </div>
  );
}

/* 减法可视化:从 a 里拿走 b(末尾打叉) */
function SubViz({ a, b }) {
  const frames = buildCells(a, 0, b);
  return (
    <div style={{ display: 'flex', gap: 22, flexWrap: 'wrap', justifyContent: 'center' }}>
      {frames.map((cells, i) => <Frame key={i} cells={cells} />)}
    </div>
  );
}

/* 数的分解:n = 5 + (n-5),突出5为基数 */
function Decompose({ n }) {
  const five = Math.min(5, n);
  const rest = n - five;
  return (
    <div style={{ display: 'flex', alignItems: 'center', gap: 16, flexWrap: 'wrap', justifyContent: 'center' }}>
      <Group count={five} color="var(--yellow)" label="5" />
      {rest > 0 && <span className="num" style={{ fontSize: 40, color: 'var(--ink-soft)' }}>+</span>}
      {rest > 0 && <Group count={rest} color="var(--mint)" label={String(rest)} />}
    </div>
  );
}
function Group({ count, color, label }) {
  return (
    <div style={{ textAlign: 'center' }}>
      <div style={{ display: 'flex', gap: 6, padding: 12, background: '#fff', borderRadius: 16,
        boxShadow: 'inset 0 0 0 3px rgba(74,59,107,.08)' }}>
        {Array.from({ length: count }).map((_, i) =>
          <Bead key={i} size={30} color={color} delay={i * 50} />)}
      </div>
      <div className="num" style={{ marginTop: 6, fontSize: 26, color }}>{label}</div>
    </div>
  );
}

/* 乘法点阵:rows 行 × cols 列 */
function DotArray({ rows, cols, size = 30 }) {
  const palette = ['var(--pink)','var(--blue)','var(--mint)','var(--purple)','var(--orange)',
    'var(--coral)','var(--yellow)','var(--green)','var(--blue)'];
  return (
    <div style={{ display: 'inline-grid', gap: 9, padding: 16, background: '#fff',
      borderRadius: 20, boxShadow: 'inset 0 0 0 3px rgba(74,59,107,.08)',
      gridTemplateColumns: `repeat(${cols}, ${size}px)` }}>
      {Array.from({ length: rows * cols }).map((_, i) =>
        <Bead key={i} size={size} color={palette[Math.floor(i / cols) % palette.length]}
          delay={i * 30} />)}
    </div>
  );
}

/* 除法分组:total 个,分成 groups 份 */
function Grouping({ total, groups }) {
  const per = total / groups;
  const colors = ['var(--pink)','var(--blue)','var(--mint)','var(--purple)','var(--orange)','var(--coral)'];
  return (
    <div style={{ display: 'flex', gap: 16, flexWrap: 'wrap', justifyContent: 'center' }}>
      {Array.from({ length: groups }).map((_, g) => (
        <div key={g} className="bob" style={{ animationDelay: g * 0.2 + 's',
          padding: '14px 14px 10px', background: '#fff', borderRadius: '18px 18px 22px 22px',
          boxShadow: 'inset 0 0 0 3px rgba(74,59,107,.08)', textAlign: 'center' }}>
          <div style={{ display: 'grid', gridTemplateColumns: `repeat(${Math.min(per,3)}, 28px)`, gap: 6,
            justifyContent: 'center', minHeight: 28 }}>
            {Array.from({ length: per }).map((_, i) =>
              <Bead key={i} size={26} color={colors[g % colors.length]} delay={(g * per + i) * 40} />)}
          </div>
          <div style={{ fontSize: 26, marginTop: 6 }}>🧺</div>
        </div>
      ))}
    </div>
  );
}

/* 九九乘法表(可交互/可高亮) */
function MultTable({ highlight, onPick, maxN = 9 }) {
  const [hover, setHover] = React.useState(null);
  const hi = hover || highlight;
  const headColor = (n) => ['var(--pink)','var(--orange)','var(--yellow)','var(--green)',
    'var(--mint)','var(--blue)','var(--purple)','var(--coral)','var(--pink)'][n - 1];
  return (
    <div style={{ display: 'inline-block' }}>
      <div style={{ display: 'grid', gridTemplateColumns: `repeat(${maxN + 1}, 1fr)`, gap: 5 }}>
        <div />
        {Array.from({ length: maxN }).map((_, j) => {
          const c = j + 1, on = hi && hi.c === c;
          return <div key={'h' + c} className="num" style={{ ...cellHead, background: headColor(c),
            transform: on ? 'scale(1.12)' : 'none', boxShadow: on ? '0 0 0 3px #fff, 0 4px 0 rgba(0,0,0,.15)' : 'none' }}>{c}</div>;
        })}
        {Array.from({ length: maxN }).map((_, i) => {
          const r = i + 1;
          return (
            <React.Fragment key={'r' + r}>
              <div className="num" style={{ ...cellHead, background: headColor(r),
                transform: hi && hi.r === r ? 'scale(1.12)' : 'none',
                boxShadow: hi && hi.r === r ? '0 0 0 3px #fff, 0 4px 0 rgba(0,0,0,.15)' : 'none' }}>{r}</div>
              {Array.from({ length: maxN }).map((_, j) => {
                const c = j + 1;
                const active = hi && (hi.r === r && hi.c === c);
                const inLine = hi && (hi.r === r || hi.c === c);
                const dim = hi && !inLine;
                return (
                  <button key={c} className="num"
                    onMouseEnter={() => setHover({ r, c })}
                    onMouseLeave={() => setHover(null)}
                    onClick={() => { window.Sound && Sound.pop(); window.Sound && Sound.speak(koujue(r, c));
                      onPick && onPick({ r, c }); }}
                    style={{ ...cell,
                      background: active ? 'var(--pink)' : inLine ? 'var(--pink-lt)' : '#fff',
                      color: active ? '#fff' : 'var(--ink)',
                      opacity: dim ? 0.4 : 1,
                      transform: active ? 'scale(1.14)' : 'none',
                      zIndex: active ? 2 : 1 }}>
                    {r * c}
                  </button>
                );
              })}
            </React.Fragment>
          );
        })}
      </div>
      {hi && (
        <div className="num pop-in" style={{ marginTop: 14, textAlign: 'center', fontSize: 30,
          color: 'var(--ink)' }}>
          <span style={{ color: 'var(--purple)' }}>{hi.r} × {hi.c} = {hi.r * hi.c}</span>
          <span style={{ fontFamily: 'var(--font-zh)', marginLeft: 14, color: 'var(--pink)' }}>
            {koujue(hi.r, hi.c)}
          </span>
        </div>
      )}
    </div>
  );
}
const cellHead = {
  width: '100%', aspectRatio: '1', minWidth: 34, borderRadius: 10, color: '#fff',
  display: 'flex', alignItems: 'center', justifyContent: 'center', fontSize: 20,
  transition: 'all .15s',
};
const cell = {
  width: '100%', aspectRatio: '1', minWidth: 34, border: 'none', borderRadius: 10,
  fontSize: 19, cursor: 'pointer', fontFamily: 'var(--font-num)', fontWeight: 700,
  boxShadow: 'inset 0 0 0 2px rgba(74,59,107,.06)', transition: 'all .15s',
};

Object.assign(window, {
  Bead, Frame, AddViz, SubViz, Decompose, Group, DotArray, Grouping, MultTable,
});
