// tiles.jsx — Reusable CSS/SVG mahjong tile system for MagicalKitten.
// Authentic suit faces rendered as crisp SVG on a 3D ivory tile body.
// Themeable via props. Exports to window: Tile, TileRow, CatMark, Mat.
//
// <Tile suit="dot|bamboo|char|wind|dragon|cat|flower" value={n|char} w={120}
//        ink="#…" red="#…" green="#…" blue="#…" body="ivory|jade|ink|rainbow"
//        tilt={-6} lift />
//
// suit values:
//   dot     value 1-9
//   bamboo  value 1-9   (1 = bird)
//   char    value 1-9   (number + 萬)
//   wind    value 'E'|'S'|'W'|'N'  → 東南西北
//   dragon  value 'red'|'green'|'white' → 中 / 發 / 框
//   cat     value 1-3   (the house signature — 3 painterly cat poses)
//   flower  value 1-4

(function () {
  if (typeof document === 'undefined' || document.getElementById('mk-tile-styles')) return;
  const s = document.createElement('style');
  s.id = 'mk-tile-styles';
  s.textContent = `
  .mk-tile{position:relative;flex:0 0 auto;border-radius:calc(var(--tw)*0.15);
    width:var(--tw);height:calc(var(--tw)*1.38);
    background:
      linear-gradient(158deg,#fffdf8 0%,#fbf6ec 42%,#f1e8d6 100%);
    box-shadow:
      inset 0 calc(var(--tw)*0.018) calc(var(--tw)*0.02) rgba(255,255,255,.95),
      inset 0 calc(var(--tw)*-0.06) calc(var(--tw)*0.07) rgba(120,98,60,.16),
      inset calc(var(--tw)*0.03) 0 calc(var(--tw)*0.05) rgba(255,255,255,.5),
      inset calc(var(--tw)*-0.03) 0 calc(var(--tw)*0.05) rgba(150,125,80,.12),
      0 calc(var(--tw)*0.10) 0 #d9c9a6,
      0 calc(var(--tw)*0.115) 0 #c8b58a,
      0 calc(var(--tw)*0.12) calc(var(--tw)*0.06) rgba(60,44,20,.30),
      0 calc(var(--tw)*0.22) calc(var(--tw)*0.18) rgba(40,28,10,.22);
    transition:transform .45s cubic-bezier(.2,.8,.25,1), box-shadow .45s;}
  .mk-tile.jade{background:linear-gradient(158deg,#eafaf2 0%,#cdeede 45%,#a7d8c2 100%);}
  .mk-tile.ink{background:linear-gradient(158deg,#3a3a42 0%,#26262d 50%,#171720 100%);
    box-shadow:
      inset 0 calc(var(--tw)*0.018) calc(var(--tw)*0.02) rgba(255,255,255,.14),
      inset 0 calc(var(--tw)*-0.06) calc(var(--tw)*0.07) rgba(0,0,0,.5),
      0 calc(var(--tw)*0.10) 0 #0c0c12,
      0 calc(var(--tw)*0.12) calc(var(--tw)*0.06) rgba(0,0,0,.5),
      0 calc(var(--tw)*0.22) calc(var(--tw)*0.2) rgba(0,0,0,.45);}
  .mk-tile.rainbow{background:
    linear-gradient(158deg,#fff 0%,#fdf7ff 60%,#f3e9ff 100%);}
  .mk-tile .mk-face{position:absolute;inset:7% 9% 11%;display:flex;align-items:center;
    justify-content:center;}
  .mk-tile .mk-face svg{width:100%;height:100%;overflow:visible;}
  .mk-tile.lift:hover{transform:translateY(calc(var(--tw)*-0.09)) rotate(0deg);}
  .mk-tilt{transform:rotate(var(--tilt,0deg));}
  .mk-row{display:flex;align-items:flex-end;}
  .mk-mat{position:relative;border-radius:10px;overflow:hidden;}
  `;
  document.head.appendChild(s);
})();

// ---- helpers -------------------------------------------------------------
const cjkFont = '"Noto Serif SC", "Songti SC", serif';

function dotPositions(n) {
  const P = {
    1: [[50, 50]],
    2: [[50, 26], [50, 74]],
    3: [[26, 22], [50, 50], [74, 78]],
    4: [[30, 28], [70, 28], [30, 72], [70, 72]],
    5: [[28, 26], [72, 26], [50, 50], [28, 74], [72, 74]],
    6: [[30, 24], [70, 24], [30, 50], [70, 50], [30, 76], [70, 76]],
    7: [[30, 20], [70, 20], [30, 44], [70, 44], [50, 62], [30, 80], [70, 80]],
    8: [[30, 20], [70, 20], [30, 40], [70, 40], [30, 60], [70, 60], [30, 80], [70, 80]],
    9: [[26, 22], [50, 22], [74, 22], [26, 50], [50, 50], [74, 50], [26, 78], [50, 78], [74, 78]],
  };
  return P[n] || P[1];
}

function Dot({ cx, cy, r, c1, c2 }) {
  const id = `d${Math.round(cx)}_${Math.round(cy)}_${c1.replace('#', '')}`;
  return (
    <g>
      <defs>
        <radialGradient id={id} cx="38%" cy="34%" r="75%">
          <stop offset="0%" stopColor="#fff" stopOpacity="0.9" />
          <stop offset="38%" stopColor={c1} />
          <stop offset="100%" stopColor={c2} />
        </radialGradient>
      </defs>
      <circle cx={cx} cy={cy} r={r} fill={`url(#${id})`} stroke={c2} strokeWidth="1.1" />
      <circle cx={cx} cy={cy} r={r * 0.4} fill="none" stroke="#fff" strokeOpacity="0.5" strokeWidth="1" />
    </g>
  );
}

function Dots({ n, red, green, blue }) {
  const pos = dotPositions(n);
  const r = n <= 2 ? 13 : n <= 5 ? 11 : 9.5;
  // traditional-ish colouring per count
  const colorFor = (i) => {
    if (n === 1) return [red, '#9c2b1e'];
    if (n === 9) { const row = Math.floor(i / 3); return [[green, blue, red][row], '#222']; }
    if (n === 6) return i < 3 ? [green, '#1f5e43'] : [red, '#9c2b1e'];
    return i % 2 ? [blue, '#1c3b66'] : [green, '#1f5e43'];
  };
  return (
    <svg viewBox="0 0 100 100">
      {pos.map(([cx, cy], i) => {
        const [c1, c2] = colorFor(i);
        return <Dot key={i} cx={cx} cy={cy} r={r} c1={c1} c2={c2} />;
      })}
    </svg>
  );
}

function Stick({ x, y, h, c1, c2 }) {
  return (
    <g>
      <rect x={x - 3.4} y={y - h / 2} width="6.8" height={h} rx="3.2" fill={c1} stroke={c2} strokeWidth="1" />
      <rect x={x - 1.6} y={y - h / 2 + 2} width="1.4" height={h - 4} rx="0.7" fill="#fff" fillOpacity="0.45" />
      <ellipse cx={x} cy={y} rx="4.6" ry="2.4" fill={c2} />
    </g>
  );
}

function Bamboo({ n, red, green, blue }) {
  if (n === 1) {
    // 1 bamboo = stylised sparrow/bird, here a refined house sparrow
    return (
      <svg viewBox="0 0 100 100">
        <ellipse cx="50" cy="58" rx="20" ry="24" fill={green} stroke="#1f5e43" strokeWidth="1.4" />
        <ellipse cx="50" cy="52" rx="12" ry="14" fill="#fff" fillOpacity="0.35" />
        <circle cx="50" cy="30" r="12" fill={red} stroke="#9c2b1e" strokeWidth="1.3" />
        <circle cx="46" cy="28" r="2.4" fill="#fff" />
        <circle cx="46" cy="28" r="1.1" fill="#222" />
        <path d="M38 30 L28 27 L38 34 Z" fill="#e8a83c" />
        <path d="M50 80 Q44 92 40 95 M50 80 Q56 92 60 95" stroke="#1f5e43" strokeWidth="2.4" fill="none" strokeLinecap="round" />
        <path d="M64 56 Q80 50 86 60 Q74 60 66 66 Z" fill={green} stroke="#1f5e43" strokeWidth="1" />
      </svg>
    );
  }
  const rows = { 2: [[50, 2]], 3: [[50, 1], [50, 2]], 4: [[2, 2]], 5: [[2, 1], [50, 1], [2, 2]],
    6: [[3, 2]], 7: [[3, 1], [50, 1], [3, 2]], 8: [[2, 2], [2, 2]], 9: [[3, 3]] };
  // Build explicit layouts
  const layouts = {
    2: [[50, 30], [50, 70]],
    3: [[50, 22], [50, 50], [50, 78]],
    4: [[34, 30], [66, 30], [34, 70], [66, 70]],
    5: [[30, 28], [70, 28], [50, 50], [30, 72], [70, 72]],
    6: [[30, 26], [50, 26], [70, 26], [30, 74], [50, 74], [70, 74]],
    7: [[50, 20], [30, 44], [70, 44], [30, 50], [70, 50], [34, 76], [66, 76]],
    8: [[30, 26], [50, 26], [70, 26], [30, 50], [70, 50], [30, 74], [50, 74], [70, 74]],
    9: [[28, 24], [50, 24], [72, 24], [28, 50], [50, 50], [72, 50], [28, 76], [50, 76], [72, 76]],
  };
  const pts = layouts[n] || layouts[2];
  const h = n <= 3 ? 30 : n <= 6 ? 26 : 20;
  const colorFor = (i) => {
    if (n === 7) return i === 0 ? [red, '#9c2b1e'] : [green, '#1f5e43'];
    if (n === 8) return [green, '#1f5e43'];
    if (n === 9) { const c = i % 3; return [[green, red, blue][c], '#222']; }
    return [green, '#1f5e43'];
  };
  return (
    <svg viewBox="0 0 100 100">
      {pts.map(([x, y], i) => { const [c1, c2] = colorFor(i); return <Stick key={i} x={x} y={y} h={h} c1={c1} c2={c2} />; })}
    </svg>
  );
}

const CN = ['', '一', '二', '三', '四', '五', '六', '七', '八', '九'];
function CharTile({ n, red, ink }) {
  return (
    <svg viewBox="0 0 100 100">
      <text x="50" y="40" textAnchor="middle" fontFamily={cjkFont} fontSize="46" fontWeight="600" fill={ink}>{CN[n]}</text>
      <text x="50" y="92" textAnchor="middle" fontFamily={cjkFont} fontSize="44" fontWeight="700" fill={red}>萬</text>
    </svg>
  );
}

function WindTile({ value, ink }) {
  const m = { E: '東', S: '南', W: '西', N: '北' };
  return (
    <svg viewBox="0 0 100 100">
      <text x="50" y="74" textAnchor="middle" fontFamily={cjkFont} fontSize="68" fontWeight="600" fill={ink}>{m[value] || '東'}</text>
    </svg>
  );
}

function DragonTile({ value, red, green }) {
  if (value === 'white') {
    return (
      <svg viewBox="0 0 100 100">
        <rect x="16" y="12" width="68" height="76" rx="6" fill="none" stroke="#21508f" strokeWidth="4" />
        <rect x="24" y="20" width="52" height="60" rx="3" fill="none" stroke="#21508f" strokeWidth="1.5" />
      </svg>
    );
  }
  const ch = value === 'green' ? '發' : '中';
  const c = value === 'green' ? green : red;
  return (
    <svg viewBox="0 0 100 100">
      <text x="50" y="76" textAnchor="middle" fontFamily={cjkFont} fontSize="70" fontWeight="700" fill={c}>{ch}</text>
    </svg>
  );
}

// The MagicalKitten signature — a refined seated cat. Three poses; rainbow
// optional. Kept geometric and calm so it reads luxe, not clip-art.
function CatTile({ value = 1, rainbow, ink = '#23202b' }) {
  const rid = `cat-rb-${value}`;
  const fur = rainbow ? `url(#${rid})` : ink;
  return (
    <svg viewBox="0 0 100 100">
      {rainbow && (
        <defs>
          <linearGradient id={rid} x1="0" y1="0" x2="1" y2="1">
            <stop offset="0%" stopColor="#ff7a9c" />
            <stop offset="28%" stopColor="#ffb454" />
            <stop offset="52%" stopColor="#ffe25e" />
            <stop offset="72%" stopColor="#5ec98a" />
            <stop offset="100%" stopColor="#5aa9f2" />
          </linearGradient>
        </defs>
      )}
      {/* seated body */}
      <path d="M50 44 C30 44 24 70 26 86 C26 90 30 92 38 92 L62 92 C70 92 74 90 74 86 C76 70 70 44 50 44 Z" fill={fur} />
      {/* tail curl */}
      <path d="M72 84 C90 82 92 64 80 58" fill="none" stroke={fur} strokeWidth="7" strokeLinecap="round" />
      {/* head */}
      <circle cx="50" cy="36" r="22" fill={fur} />
      {/* ears */}
      <path d="M32 24 L30 6 L46 18 Z" fill={fur} />
      <path d="M68 24 L70 6 L54 18 Z" fill={fur} />
      <path d="M34 20 L33 11 L41 17 Z" fill="#ffd1dd" />
      <path d="M66 20 L67 11 L59 17 Z" fill="#ffd1dd" />
      {/* face */}
      <g fill="#fff">
        <ellipse cx="42" cy="36" rx="4.6" ry="5.4" />
        <ellipse cx="58" cy="36" rx="4.6" ry="5.4" />
      </g>
      <g fill="#1c1a22">
        <circle cx="42" cy="37" r="2.4" />
        <circle cx="58" cy="37" r="2.4" />
      </g>
      <path d="M50 43 l-3 3 h6 Z" fill="#ff9ab0" />
      <path d="M50 46 q-4 4 -9 3 M50 46 q4 4 9 3" stroke="#fff" strokeWidth="1.4" fill="none" strokeLinecap="round" />
      {/* whiskers */}
      <g stroke={rainbow ? '#cdb4ff' : '#b9b2c4'} strokeWidth="1.1" strokeLinecap="round">
        <path d="M36 40 L20 37 M36 43 L21 45" />
        <path d="M64 40 L80 37 M64 43 L79 45" />
      </g>
    </svg>
  );
}

function Flower({ value = 1, red, green, blue }) {
  const c = [red, green, blue, '#c98f2e'][(value - 1) % 4];
  return (
    <svg viewBox="0 0 100 100">
      {[0, 1, 2, 3, 4].map((i) => (
        <ellipse key={i} cx="50" cy="30" rx="9" ry="18" fill={c} fillOpacity="0.85"
          transform={`rotate(${i * 72} 50 50)`} />
      ))}
      <circle cx="50" cy="50" r="9" fill="#f4d35e" stroke="#caa12e" strokeWidth="1.5" />
    </svg>
  );
}

function Tile({ suit = 'dot', value = 1, w = 110, body = 'ivory', tilt = 0, lift = true,
  red = '#c0392b', green = '#1f7a4d', blue = '#2a5d9c', ink = '#23202b', rainbow = false, style = {} }) {
  let face;
  if (suit === 'dot') face = <Dots n={value} red={red} green={green} blue={blue} />;
  else if (suit === 'bamboo') face = <Bamboo n={value} red={red} green={green} blue={blue} />;
  else if (suit === 'char') face = <CharTile n={value} red={red} ink={ink} />;
  else if (suit === 'wind') face = <WindTile value={value} ink={ink} />;
  else if (suit === 'dragon') face = <DragonTile value={value} red={red} green={green} />;
  else if (suit === 'cat') face = <CatTile value={value} rainbow={rainbow} ink={ink} />;
  else if (suit === 'flower') face = <Flower value={value} red={red} green={green} blue={blue} />;
  const cls = `mk-tile ${body !== 'ivory' ? body : ''} ${lift ? 'lift' : ''}`.trim();
  return (
    <div className={cls} style={{ '--tw': `${w}px`, '--tilt': `${tilt}deg`, transform: tilt ? `rotate(${tilt}deg)` : undefined, ...style }}>
      <div className="mk-face">{face}</div>
    </div>
  );
}

// A neat row/fan of tiles.
function TileRow({ tiles, w = 90, overlap = 0, gap = 8, fan = 0, body, align = 'flex-end', style = {} }) {
  return (
    <div className="mk-row" style={{ gap: overlap ? 0 : gap, alignItems: align, ...style }}>
      {tiles.map((t, i) => {
        const mid = (tiles.length - 1) / 2;
        const rot = fan ? (i - mid) * fan : (t.tilt || 0);
        return (
          <div key={i} style={{ marginLeft: overlap && i ? -overlap : 0, zIndex: i,
            transformOrigin: 'bottom center', transform: fan ? `rotate(${rot}deg) translateY(${Math.abs(i - mid) * fan * 0.8}px)` : undefined }}>
            <Tile w={w} body={body} {...t} tilt={fan ? 0 : t.tilt} />
          </div>
        );
      })}
    </div>
  );
}

// A felt/leather playing mat with stitched border.
function Mat({ w = 320, h = 200, color = '#1f4d3a', edge = '#0d2c20', stitch = '#caa564', style = {}, children }) {
  return (
    <div className="mk-mat" style={{ width: w, height: h,
      background: `radial-gradient(120% 120% at 50% 0%, ${color} 0%, ${edge} 120%)`,
      boxShadow: `inset 0 0 0 6px ${edge}, inset 0 0 0 8px ${stitch}33, inset 0 2px 30px rgba(0,0,0,.4), 0 20px 50px rgba(0,0,0,.35)`,
      ...style }}>
      <div style={{ position: 'absolute', inset: 11, border: `1.5px dashed ${stitch}`, borderRadius: 6, opacity: 0.7 }} />
      {children}
    </div>
  );
}

Object.assign(window, { Tile, TileRow, CatMark: CatTile, Mat });
