// app-pixelgram.jsx — 32x32 pixel drawing tool, shared between Branden & Cindy

const { useState: useP, useEffect: useEP, useRef: useRP } = React;

const GRID = 32;
const PIXEL = 14; // canvas display size per pixel

// Curated palette — warm tones that work in light and dark mode
const PALETTE = [
  '#000000', '#3d3a36', '#7a766c', '#cdc7b8', '#fbfaf7', '#ffffff',
  '#c97a4a', '#e8a86b', '#f3dccb', '#b89968', '#d4b88a',
  '#2b3a55', '#4d6088', '#7faedb', '#c4d2e6',
  '#7a9b7e', '#a4b89a', '#dde3d3',
  '#a87aff', '#6affd8', '#4ad9ff', '#ff9ec7',
];

const BLANK = () => Array(GRID * GRID).fill(null);

// Stored "received" drawings (mock — what the partner sent)
const SAMPLE_HEART = (() => {
  const g = BLANK();
  // Simple pixel heart at center
  const heart = [
    '..XX...XX..',
    '.XCCX.XCCX.',
    'XCCCCXCCCCX',
    'XCCCCCCCCCX',
    'XCCCCCCCCCX',
    '.XCCCCCCCX.',
    '..XCCCCCX..',
    '...XCCCX...',
    '....XCX....',
    '.....X.....',
  ];
  const offX = 11, offY = 11;
  heart.forEach((row, y) => {
    [...row].forEach((ch, x) => {
      if (ch === 'X') g[(y + offY) * GRID + (x + offX)] = '#3d3a36';
      if (ch === 'C') g[(y + offY) * GRID + (x + offX)] = '#c97a4a';
    });
  });
  return g;
})();

const SAMPLE_COFFEE = (() => {
  const g = BLANK();
  // mug
  for (let y = 14; y < 24; y++) {
    for (let x = 10; x < 20; x++) {
      if (y === 14 || y === 23 || x === 10 || x === 19) g[y*GRID+x] = '#3d3a36';
      else g[y*GRID+x] = '#fbfaf7';
    }
  }
  // handle
  for (let y = 16; y < 22; y++) {
    g[y*GRID+20] = '#3d3a36';
    if (y === 16 || y === 21) g[y*GRID+21] = '#3d3a36';
    g[y*GRID+22] = y === 16 || y === 21 ? '#3d3a36' : null;
  }
  g[17*GRID+22] = '#3d3a36'; g[20*GRID+22] = '#3d3a36';
  // coffee
  for (let y = 15; y < 17; y++) for (let x = 11; x < 19; x++) g[y*GRID+x] = '#7a4a2b';
  // steam
  [[12, 13], [13, 12], [14, 13], [15, 12], [16, 13], [17, 12]].forEach(([y, x]) => g[y*GRID+x] = '#cdc7b8');
  return g;
})();

const PixelCanvas = ({ grid, onPixel, size = PIXEL, interactive = true, who = 'B' }) => {
  const ref = useRP(null);
  const [drawing, setDrawing] = useP(false);
  const total = GRID * size;
  return (
    <div
      ref={ref}
      onMouseDown={interactive ? (e) => {
        setDrawing(true);
        const rect = ref.current.getBoundingClientRect();
        const x = Math.floor((e.clientX - rect.left) / size);
        const y = Math.floor((e.clientY - rect.top) / size);
        if (x >= 0 && x < GRID && y >= 0 && y < GRID) onPixel(y * GRID + x);
      } : undefined}
      onMouseMove={interactive && drawing ? (e) => {
        const rect = ref.current.getBoundingClientRect();
        const x = Math.floor((e.clientX - rect.left) / size);
        const y = Math.floor((e.clientY - rect.top) / size);
        if (x >= 0 && x < GRID && y >= 0 && y < GRID) onPixel(y * GRID + x);
      } : undefined}
      onMouseUp={() => setDrawing(false)}
      onMouseLeave={() => setDrawing(false)}
      style={{
        width: total, height: total,
        background: '#fbfaf7',
        backgroundImage: interactive
          ? `linear-gradient(to right, rgba(0,0,0,.06) 1px, transparent 1px), linear-gradient(to bottom, rgba(0,0,0,.06) 1px, transparent 1px)`
          : 'none',
        backgroundSize: `${size}px ${size}px`,
        border: '1px solid #ece8de',
        borderRadius: 6,
        position: 'relative',
        cursor: interactive ? 'crosshair' : 'default',
        flexShrink: 0,
        userSelect: 'none',
        boxShadow: 'inset 0 0 0 1px rgba(255,255,255,0.5)',
      }}
    >
      <svg width={total} height={total} style={{ position: 'absolute', inset: 0, pointerEvents: 'none' }}>
        {grid.map((c, i) => {
          if (!c) return null;
          const x = i % GRID, y = Math.floor(i / GRID);
          return <rect key={i} x={x * size} y={y * size} width={size} height={size} fill={c} shapeRendering="crispEdges" />;
        })}
      </svg>
    </div>
  );
};

// Mini preview (no grid)
const PixelPreview = ({ grid, size = 4 }) => {
  const total = GRID * size;
  return (
    <svg width={total} height={total} viewBox={`0 0 ${GRID} ${GRID}`} style={{ display: 'block', borderRadius: 4, background: '#fbfaf7' }}>
      {grid.map((c, i) => {
        if (!c) return null;
        return <rect key={i} x={i % GRID} y={Math.floor(i / GRID)} width="1" height="1" fill={c} shapeRendering="crispEdges" />;
      })}
    </svg>
  );
};

// LocalStorage-backed message thread
const MSG_KEY = 'twogether_pixel_msgs_v1';
const loadMsgs = () => {
  try { return JSON.parse(localStorage.getItem(MSG_KEY)) || null; } catch { return null; }
};
const saveMsgs = (msgs) => {
  try { localStorage.setItem(MSG_KEY, JSON.stringify(msgs)); } catch {}
};

const DEFAULT_MSGS = [
  { id: 'm1', from: 'C', when: 'Yesterday · 9:14p',  caption: 'Thinking of you', grid: SAMPLE_HEART },
  { id: 'm2', from: 'B', when: '2 days ago · 7:02a', caption: 'Made you a coffee', grid: SAMPLE_COFFEE },
];

const PixelComposer = ({ onSend, onCancel, who, dark }) => {
  const [grid, setGrid] = useP(BLANK());
  const [color, setColor] = useP('#c97a4a');
  const [tool, setTool] = useP('paint');
  const [caption, setCaption] = useP('');
  const [history, setHistory] = useP([]);

  const paint = (i) => {
    setHistory(h => [...h.slice(-30), grid]);
    const g = [...grid];
    g[i] = tool === 'erase' ? null : color;
    setGrid(g);
  };
  const undo = () => {
    if (!history.length) return;
    setGrid(history[history.length - 1]);
    setHistory(h => h.slice(0, -1));
  };
  const clear = () => { setHistory(h => [...h, grid]); setGrid(BLANK()); };
  const filled = grid.filter(Boolean).length;

  return (
    <div style={{
      display: 'flex', gap: 18, alignItems: 'flex-start',
      padding: 18, borderRadius: 14,
      background: dark ? 'rgba(255,255,255,0.03)' : '#fdfcf9',
      border: `1px solid ${dark ? 'rgba(255,255,255,0.08)' : '#ece8de'}`,
    }}>
      {/* Canvas */}
      <div>
        <PixelCanvas grid={grid} onPixel={paint} who={who} />
        <div style={{ display: 'flex', justifyContent: 'space-between', alignItems: 'center', marginTop: 8, fontSize: 10.5, color: dark ? 'rgba(255,255,255,0.5)' : '#7a766c' }}>
          <span>32 × 32 · {filled} pixels</span>
          <span style={{ display: 'inline-flex', alignItems: 'center', gap: 6 }}>
            <Avatar who={who} size={14} /> drawing as {window.PEOPLE[who].name}
          </span>
        </div>
      </div>

      {/* Tools */}
      <div style={{ flex: 1, minWidth: 0, display: 'flex', flexDirection: 'column', gap: 14 }}>
        <div>
          <div style={{ fontSize: 10, letterSpacing: '0.12em', textTransform: 'uppercase', color: dark ? 'rgba(255,255,255,0.5)' : '#7a766c', marginBottom: 8 }}>Tool</div>
          <div style={{ display: 'flex', gap: 6 }}>
            {[['paint', 'Paint'], ['erase', 'Erase']].map(([k, lbl]) => (
              <button key={k} onClick={() => setTool(k)} style={{
                flex: 1, padding: '8px 10px', borderRadius: 8,
                border: `1px solid ${tool === k ? (dark ? 'rgba(255,255,255,0.4)' : '#1d2638') : (dark ? 'rgba(255,255,255,0.12)' : '#ece8de')}`,
                background: tool === k ? (dark ? 'rgba(255,255,255,0.08)' : '#1d2638') : 'transparent',
                color: tool === k ? (dark ? '#fff' : '#fbfaf7') : (dark ? 'rgba(255,255,255,0.7)' : '#534e44'),
                fontSize: 11.5, fontWeight: 500, cursor: 'pointer', fontFamily: 'Inter, system-ui',
              }}>{lbl}</button>
            ))}
            <button onClick={undo} style={toolBtn(dark)}>Undo</button>
            <button onClick={clear} style={toolBtn(dark)}>Clear</button>
          </div>
        </div>

        <div>
          <div style={{ fontSize: 10, letterSpacing: '0.12em', textTransform: 'uppercase', color: dark ? 'rgba(255,255,255,0.5)' : '#7a766c', marginBottom: 8 }}>Color</div>
          <div style={{ display: 'grid', gridTemplateColumns: 'repeat(11, 1fr)', gap: 4, maxWidth: 280 }}>
            {PALETTE.map(c => (
              <button key={c} onClick={() => { setColor(c); setTool('paint'); }} style={{
                width: 22, height: 22, borderRadius: 5, border: 'none',
                background: c, cursor: 'pointer',
                boxShadow: color === c ? `0 0 0 2px ${dark ? '#fff' : '#1d2638'}, 0 0 0 4px ${dark ? '#16112a' : '#fbfaf7'}` : 'inset 0 0 0 1px rgba(0,0,0,0.1)',
                transition: 'transform .1s',
                transform: color === c ? 'scale(1.1)' : 'none',
              }} />
            ))}
          </div>
        </div>

        <div>
          <div style={{ fontSize: 10, letterSpacing: '0.12em', textTransform: 'uppercase', color: dark ? 'rgba(255,255,255,0.5)' : '#7a766c', marginBottom: 6 }}>Caption (optional)</div>
          <input type="text" value={caption} onChange={e => setCaption(e.target.value)}
            placeholder="A little note…" maxLength={60}
            style={{
              width: '100%', padding: '8px 10px', borderRadius: 8,
              border: `1px solid ${dark ? 'rgba(255,255,255,0.12)' : '#ece8de'}`,
              background: dark ? 'rgba(0,0,0,0.2)' : '#fbfaf7',
              color: dark ? '#fff' : '#1d2638',
              fontSize: 12, fontFamily: 'Inter, system-ui',
            }}
          />
        </div>

        <div style={{ display: 'flex', gap: 8, marginTop: 'auto' }}>
          <button
            onClick={() => onSend({ grid, caption })}
            disabled={!filled}
            style={{
              flex: 1, padding: '10px 14px', borderRadius: 8, border: 'none',
              background: filled ? '#1d2638' : (dark ? 'rgba(255,255,255,0.08)' : '#ece8de'),
              color: filled ? '#fbfaf7' : (dark ? 'rgba(255,255,255,0.4)' : '#a89889'),
              fontSize: 12, fontWeight: 500, fontFamily: 'Inter, system-ui',
              cursor: filled ? 'pointer' : 'not-allowed',
              display: 'inline-flex', alignItems: 'center', justifyContent: 'center', gap: 6,
            }}>
            <Icon name="arrow-right" size={13} stroke={filled ? '#fbfaf7' : '#a89889'} />
            Send to {who === 'B' ? 'Cindy' : 'Branden'}
          </button>
          <button onClick={onCancel} style={toolBtn(dark, true)}>Cancel</button>
        </div>
      </div>
    </div>
  );
};

const toolBtn = (dark, wide) => ({
  padding: '8px 12px', borderRadius: 8,
  border: `1px solid ${dark ? 'rgba(255,255,255,0.12)' : '#ece8de'}`,
  background: 'transparent',
  color: dark ? 'rgba(255,255,255,0.7)' : '#534e44',
  fontSize: 11.5, fontWeight: 500, cursor: 'pointer', fontFamily: 'Inter, system-ui',
  flex: wide ? 0 : 'none',
});

// Public widget — full pixelgram view
const PixelgramView = ({ activeUser = 'B', dark = false, density = 'cozy' }) => {
  const [msgs, setMsgs] = useP(() => loadMsgs() || DEFAULT_MSGS);
  const [composing, setComposing] = useP(false);
  const [viewing, setViewing] = useP(null);

  const send = ({ grid, caption }) => {
    const m = {
      id: 'm' + Date.now(),
      from: activeUser,
      when: 'Just now',
      caption: caption || (activeUser === 'B' ? 'For Cindy' : 'For Branden'),
      grid,
    };
    const next = [m, ...msgs];
    setMsgs(next); saveMsgs(next); setComposing(false);
  };

  return (
    <div>
      <div style={{ display: 'flex', alignItems: 'flex-end', justifyContent: 'space-between', marginBottom: 14 }}>
        <div>
          <div style={{ fontSize: 10.5, letterSpacing: '0.12em', textTransform: 'uppercase', color: dark ? 'rgba(255,255,255,0.5)' : '#7a766c', marginBottom: 4, display: 'flex', alignItems: 'center', gap: 6 }}>
            <Icon name="heart" size={11} stroke="#c97a4a" /> Couple-grams · 32 × 32
          </div>
          <h2 style={{ margin: 0, fontFamily: 'Newsreader, serif', fontWeight: 500, fontSize: 24, letterSpacing: '-0.01em', color: dark ? '#fff' : '#1d2638' }}>
            Little drawings, just for each other
          </h2>
        </div>
        {!composing && (
          <button onClick={() => setComposing(true)} style={{
            padding: '9px 14px', borderRadius: 8, border: 'none',
            background: '#1d2638', color: '#fbfaf7', fontSize: 12, fontWeight: 500,
            fontFamily: 'Inter, system-ui', cursor: 'pointer',
            display: 'inline-flex', alignItems: 'center', gap: 6,
          }}>
            <Icon name="plus" size={13} stroke="#fbfaf7" /> Draw something
          </button>
        )}
      </div>

      {composing && (
        <div style={{ marginBottom: 16 }}>
          <PixelComposer who={activeUser} dark={dark} onSend={send} onCancel={() => setComposing(false)} />
        </div>
      )}

      {/* Gallery */}
      <div style={{ display: 'grid', gridTemplateColumns: 'repeat(auto-fill, minmax(180px, 1fr))', gap: 12 }}>
        {msgs.map(m => {
          const isMine = m.from === activeUser;
          const partnerName = m.from === 'B' ? 'Branden' : 'Cindy';
          return (
            <div key={m.id} onClick={() => setViewing(m)} style={{
              padding: 10, borderRadius: 12,
              background: dark ? 'rgba(255,255,255,0.04)' : '#fdfcf9',
              border: `1px solid ${dark ? 'rgba(255,255,255,0.08)' : '#ece8de'}`,
              cursor: 'pointer',
              boxShadow: isMine ? 'none' : (dark ? '0 0 24px rgba(201,122,74,0.15)' : '0 0 0 1px rgba(201,122,74,0.15), 0 4px 16px rgba(201,122,74,0.08)'),
            }}>
              <div style={{ position: 'relative', background: '#fbfaf7', borderRadius: 8, padding: 6 }}>
                <PixelPreview grid={m.grid} size={4} />
                {!isMine && (
                  <span style={{
                    position: 'absolute', top: 6, right: 6,
                    padding: '2px 6px', borderRadius: 999,
                    background: '#c97a4a', color: '#fbfaf7', fontSize: 8.5, fontWeight: 600, letterSpacing: '0.06em', textTransform: 'uppercase',
                  }}>New</span>
                )}
              </div>
              <div style={{ display: 'flex', alignItems: 'center', gap: 6, marginTop: 8 }}>
                <Avatar who={m.from} size={16} />
                <span style={{ fontSize: 11, color: dark ? '#fff' : '#1d2638', fontWeight: 500 }}>{isMine ? 'You' : partnerName}</span>
                <span style={{ flex: 1 }} />
                <span style={{ fontSize: 9.5, color: dark ? 'rgba(255,255,255,0.4)' : '#7a766c' }}>{m.when}</span>
              </div>
              <div style={{ fontSize: 11.5, color: dark ? 'rgba(255,255,255,0.7)' : '#534e44', marginTop: 4, fontStyle: 'italic', fontFamily: 'Newsreader, serif' }}>
                "{m.caption}"
              </div>
            </div>
          );
        })}
      </div>

      {/* Lightbox */}
      {viewing && (
        <div onClick={() => setViewing(null)} style={{
          position: 'fixed', inset: 0, background: 'rgba(10,8,12,0.7)', zIndex: 9999,
          display: 'flex', alignItems: 'center', justifyContent: 'center', padding: 20,
        }}>
          <div onClick={e => e.stopPropagation()} style={{
            background: dark ? '#16112a' : '#fbfaf7', borderRadius: 16, padding: 24,
            display: 'flex', gap: 20, maxWidth: 720, alignItems: 'center',
            border: `1px solid ${dark ? 'rgba(255,255,255,0.1)' : '#ece8de'}`,
          }}>
            <PixelCanvas grid={viewing.grid} onPixel={() => {}} size={12} interactive={false} />
            <div style={{ minWidth: 200 }}>
              <div style={{ display: 'flex', alignItems: 'center', gap: 8, marginBottom: 10 }}>
                <Avatar who={viewing.from} size={28} />
                <div>
                  <div style={{ fontSize: 13, color: dark ? '#fff' : '#1d2638', fontWeight: 500 }}>
                    From {viewing.from === activeUser ? 'you' : (viewing.from === 'B' ? 'Branden' : 'Cindy')}
                  </div>
                  <div style={{ fontSize: 10.5, color: dark ? 'rgba(255,255,255,0.5)' : '#7a766c' }}>{viewing.when}</div>
                </div>
              </div>
              <p style={{ margin: 0, fontFamily: 'Newsreader, serif', fontStyle: 'italic', fontSize: 17, color: dark ? '#fff' : '#1d2638', lineHeight: 1.4 }}>
                "{viewing.caption}"
              </p>
              <button onClick={() => setViewing(null)} style={{
                marginTop: 18, padding: '8px 14px', borderRadius: 8,
                border: `1px solid ${dark ? 'rgba(255,255,255,0.15)' : '#ece8de'}`,
                background: 'transparent', color: dark ? '#fff' : '#534e44',
                fontSize: 12, fontWeight: 500, cursor: 'pointer', fontFamily: 'Inter, system-ui',
              }}>Close</button>
            </div>
          </div>
        </div>
      )}
    </div>
  );
};

// Compact dashboard card — shows latest message
const PixelgramCard = ({ activeUser = 'B', onOpen, dark = false }) => {
  const [msgs] = useP(() => loadMsgs() || DEFAULT_MSGS);
  const latest = msgs.find(m => m.from !== activeUser) || msgs[0];
  if (!latest) return null;
  const partnerName = latest.from === 'B' ? 'Branden' : 'Cindy';
  return (
    <div onClick={onOpen} style={{
      padding: 14, borderRadius: 12, cursor: 'pointer',
      background: dark ? 'rgba(255,255,255,0.04)' : '#fdfcf9',
      border: `1px solid ${dark ? 'rgba(255,255,255,0.08)' : '#ece8de'}`,
      display: 'flex', gap: 12, alignItems: 'center',
    }}>
      <div style={{ background: '#fbfaf7', borderRadius: 8, padding: 4, flexShrink: 0, boxShadow: 'inset 0 0 0 1px rgba(0,0,0,0.05)' }}>
        <PixelPreview grid={latest.grid} size={2.5} />
      </div>
      <div style={{ flex: 1, minWidth: 0 }}>
        <div style={{ display: 'flex', alignItems: 'center', gap: 6, marginBottom: 3 }}>
          <Icon name="heart" size={11} stroke="#c97a4a" />
          <span style={{ fontSize: 10, letterSpacing: '0.12em', textTransform: 'uppercase', color: '#c97a4a', fontWeight: 600 }}>From {partnerName}</span>
        </div>
        <div style={{ fontFamily: 'Newsreader, serif', fontStyle: 'italic', fontSize: 14.5, color: dark ? '#fff' : '#1d2638', lineHeight: 1.3 }}>
          "{latest.caption}"
        </div>
        <div style={{ fontSize: 10, color: dark ? 'rgba(255,255,255,0.4)' : '#7a766c', marginTop: 4 }}>{latest.when} · tap to draw back</div>
      </div>
    </div>
  );
};

Object.assign(window, { PixelgramView, PixelgramCard, PixelPreview, BLANK_PIXEL: BLANK, DEFAULT_PIXEL_MSGS: DEFAULT_MSGS });
