import '../../styles/StickersTab.css';

/**
 * Emoji tab.
 *
 * A simple emoji-picker grid. Tapping an emoji rasterizes the glyph onto a
 * 100×100 transparent canvas and adds it to the design as a sticker element.
 *
 * Why rasterize rather than render the glyph live on Konva: emoji rendering
 * is OS- and browser-dependent (Apple's Color Emoji vs Segoe UI Emoji vs
 * Noto Color Emoji look quite different from each other), and the server's
 * node-canvas almost certainly doesn't have any of those fonts installed.
 * Rasterizing client-side and shipping the resulting PNG via a data URL
 * means the printed output matches what the user designed, regardless of
 * which renderer touches it.
 *
 * This used to live in StickersTab with a `variant` switch. Splitting it
 * out cleaned up the conditional rendering and matched the actual data
 * separation: image stickers are folder-driven, emojis are a static glyph
 * list.
 */

// Inline emoji list. This used to live in constants/stickers.js as the
// `STICKERS` export; that constant has been repurposed for the new
// image-sticker manifest, so the emoji catalog moved here. Keeping it
// local also means the StickersTab build doesn't pay for the emoji
// data and vice-versa — two surfaces that no longer share anything.
const EMOJIS = [
  // Faces
  '😀','😁','😂','🤣','😃','😄','😅','😆','😉','😊','😋','😎',
  '😍','😘','🥰','😗','🤔','🤨','🧐','🤓','😈','🤠','🥳','🤩',
  // Animals
  '🐶','🐱','🐭','🐹','🐰','🦊','🐻','🐼','🐨','🐯','🦁','🐮',
  '🐷','🐸','🐵','🐔','🐧','🐦','🦄','🐝','🦋','🐌','🐞','🐢',
  // Food
  '🍎','🍐','🍊','🍋','🍌','🍉','🍇','🍓','🍈','🍒','🍑','🍍',
  '🥥','🥝','🍅','🥑','🍆','🥔','🥕','🌽','🍕','🍔','🍟','🌭',
  // Sports
  '⚽','🏀','🏈','⚾','🥎','🎾','🏐','🏉','🎱','🏓','🏸','🥅',
  '⛳','🥊','🥋','🎯','⛹️','🚴','🏆','🥇','🥈','🥉','🏅','🎖️',
  // Nature
  '🌸','💐','🌹','🌺','🌻','🌼','🌷','🌱','🌲','🌳','🌴','🌵',
  '🌾','🌿','☘️','🍀','🍁','🍂','🍃','🌈','☀️','🌙','⭐','🔥',
  // Hearts / objects
  '❤️','💛','💚','💙','💜','🧡','💔','💯','✨','🌟','💫','🎵',
  '🎶','🎸','🎺','🎷','🎹','👑','💎','🎁','🎈','🎉','🎊','🔮',
];

export function EmojiTab({ onAddSticker }) {
  const handleAddEmoji = (emoji) => {
    // Rasterize the emoji edge-to-edge.
    //
    // The previous approach drew the glyph at 80% scale on a 100×100
    // canvas with `textBaseline: 'middle'`. That left ~10px of
    // transparent padding above and below the glyph because:
    //   (a) the explicit 0.8× scale factor inset the glyph; and
    //   (b) `textBaseline: 'middle'` centers the em-box, not the
    //       visual bounds — emoji glyphs are designed with vertical
    //       metrics that include space for diacritics, descenders,
    //       etc., most of which a given emoji doesn't actually use.
    //
    // The transformer handles on the design canvas then sat that
    // 10-pixel slack away from the visible glyph on every side, which
    // read as sloppy when resizing or rotating.
    //
    // Robust fix: rasterize generously, then alpha-scan to find the
    // true visual bounding box and crop the result to it. This is the
    // same approach `useBackgroundRemoval` uses post-mask, just on a
    // self-rasterized source instead of an alpha-masked one.
    //
    // Source canvas is 256×256 (vs the previous 100×100) so the cropped
    // result still has enough resolution to print crisply at the 1200px
    // print-scale target (see public/stickers/README.md for the math).
    const SOURCE = 256;
    const FONT_PX = 220; // generous; the alpha-scan crop trims the rest
    const src = document.createElement('canvas');
    src.width = SOURCE;
    src.height = SOURCE;
    const sctx = src.getContext('2d');
    sctx.font = `${FONT_PX}px Arial`;
    sctx.textAlign = 'center';
    sctx.textBaseline = 'middle';
    sctx.fillText(emoji, SOURCE / 2, SOURCE / 2);

    // Alpha-scan for the visible bbox. `data` is a flat RGBA byte array;
    // every fourth byte is alpha. ALPHA_THRESHOLD is intentionally low
    // (above 0) so faint anti-aliasing pixels at the glyph edge are
    // included in the bbox — cropping right at the solid pixels would
    // visibly clip the emoji's edges.
    const ALPHA_THRESHOLD = 8;
    const { data } = sctx.getImageData(0, 0, SOURCE, SOURCE);
    let minX = SOURCE, minY = SOURCE, maxX = -1, maxY = -1;
    for (let y = 0; y < SOURCE; y++) {
      for (let x = 0; x < SOURCE; x++) {
        if (data[(y * SOURCE + x) * 4 + 3] > ALPHA_THRESHOLD) {
          if (x < minX) minX = x;
          if (x > maxX) maxX = x;
          if (y < minY) minY = y;
          if (y > maxY) maxY = y;
        }
      }
    }

    // Fallback for the degenerate case (no visible pixels — should never
    // happen for a real emoji glyph, but keep the path defensive). Just
    // ship the uncropped source.
    let dataUrl;
    let bboxW = SOURCE;
    let bboxH = SOURCE;
    if (maxX < minX || maxY < minY) {
      dataUrl = src.toDataURL('image/png');
    } else {
      // Add 1px on each side so anti-aliased edges aren't clipped.
      const pad = 1;
      const cropX = Math.max(0, minX - pad);
      const cropY = Math.max(0, minY - pad);
      const cropW = Math.min(SOURCE, maxX + 1 + pad) - cropX;
      const cropH = Math.min(SOURCE, maxY + 1 + pad) - cropY;
      bboxW = cropW;
      bboxH = cropH;
      const out = document.createElement('canvas');
      out.width = cropW;
      out.height = cropH;
      out.getContext('2d').drawImage(src, cropX, cropY, cropW, cropH, 0, 0, cropW, cropH);
      dataUrl = out.toDataURL('image/png');
    }

    // Fit the cropped bbox into an 80×80 design-coord box, preserving
    // aspect. Same algorithm as StickersTab.handleAddSticker (image
    // stickers) and same placement: center on the print zone center
    // (150, 150) so non-square emojis don't have their top-left pinned.
    // Wide emojis (✨) and tall emojis (⛔) both end up centered.
    const fitInto = 80;
    const scale = fitInto / Math.max(bboxW, bboxH);
    const width = bboxW * scale;
    const height = bboxH * scale;
    const printCenter = 150;

    // Type 'sticker' (not 'image') so the editor can distinguish
    // emoji-rasterized stickers from user-uploaded photos. They render
    // through the same Konva component (ImageElement) but the type tag
    // localizes special-casing — e.g. ElementToolbar's photo-only
    // surfaces (filters, background removal, edit photo) gate on type.
    onAddSticker({
      type: 'sticker',
      x: printCenter - width / 2,
      y: printCenter - height / 2,
      width,
      height,
      rotation: 0,
      src: dataUrl,
      emoji,
    });
  };

  return (
    <div className="st st--emoji">
      <div className="st__grid st__grid--emoji">
        {EMOJIS.map((emoji, index) => (
          <button
            key={`${emoji}-${index}`}
            type="button"
            onClick={() => handleAddEmoji(emoji)}
            className="st__sticker"
            aria-label={`Add emoji ${emoji}`}
          >
            <span className="st__sticker-emoji">{emoji}</span>
          </button>
        ))}
      </div>
    </div>
  );
}
