// Draggable node for the tour/transit tool.
// Three rendering modes:
//   - image       : node.image is set (uploaded photo)
//   - icon        : node.icon is one of the Lucide icon names from icons.js
//   - emoji/init  : fallback (kept for compatibility / freeform notes)
function Node({
  node, selected, onSelect, onDrag, onDragEnd, onDelete,
  dragging, worldZoom,
}){
  const ref = React.useRef(null);
  const moveState = React.useRef(null);

  const onPointerDown = (e) => {
    if (e.target.closest('.delete-btn')) return;
    e.stopPropagation();
    // shiftKey is forwarded so Canvas can dispatch "copy times from this
    // node into the currently-selected one" without selecting this node.
    onSelect(node.id, { shiftKey: !!e.shiftKey });
    const startX = e.clientX, startY = e.clientY;
    const ox = node.x, oy = node.y;
    moveState.current = { startX, startY, ox, oy, moved:false };
    e.currentTarget.setPointerCapture(e.pointerId);
  };

  const onPointerMove = (e) => {
    if (!moveState.current) return;
    const { startX, startY, ox, oy } = moveState.current;
    const dx = (e.clientX - startX) / worldZoom;
    const dy = (e.clientY - startY) / worldZoom;
    if (Math.abs(dx)+Math.abs(dy) > 2) moveState.current.moved = true;
    onDrag(node.id, ox+dx, oy+dy);
  };

  const onPointerUp = (e) => {
    if (!moveState.current) return;
    const moved = moveState.current.moved;
    moveState.current = null;
    onDragEnd(node.id, moved);
    try { e.currentTarget.releasePointerCapture(e.pointerId); } catch(_){}
  };

  // (Manual edge-drawing is gone: edges are auto-derived from each node's
  // arrival/departure times. The connect-handle on the node has been
  // removed accordingly.)

  const shape = node.shape || 'square';
  // node.highlight is a hex color used for an extra accent ring around the
  // avatar. Independent of node.color (background). Used to mark "must-do
  // meeting partner" / "trip highlight" — visual is also reflected in Schedule.
  const hi = node.highlight || null;
  const avatarStyle = {
    background: node.color || '#FFFFFF',
    ...(hi ? {
      borderColor: hi,
      borderWidth: 3,
      boxShadow: `0 0 0 3px ${hexAlpha(hi, 0.25)}, 0 2px 4px rgba(15,23,42,.06), 0 4px 12px rgba(15,23,42,.08)`,
    } : {}),
  };

  let inner;
  if (node.image){
    inner = <img src={node.image} alt="" draggable="false" crossOrigin="anonymous"/>;
  } else if (node.icon && window.TourIcon){
    inner = <window.TourIcon name={node.icon} className="icon-svg"/>;
  } else if (node.emoji){
    inner = <div className="emoji">{node.emoji}</div>;
  } else {
    const ini = (node.name||'?').trim().charAt(0).toUpperCase();
    inner = <div className="initial">{ini}</div>;
  }

  return (
    <div
      ref={ref}
      className={`node${selected?' selected':''}${dragging?' dragging':''}${shape==='square'?' has-square':''}`}
      style={{ left:node.x, top:node.y }}
      onPointerDown={onPointerDown}
      onPointerMove={onPointerMove}
      onPointerUp={onPointerUp}
      onPointerCancel={onPointerUp}
    >
      <div className="ring"/>
      <div
        className={`avatar ${shape}${hi ? ' has-highlight' : ''}`}
        style={avatarStyle}
      >
        {inner}
      </div>
      {/* Highlight star — rendered as a SIBLING of .avatar (not a child) so
          it sits on a layer above the avatar and isn't clipped by avatar's
          overflow:hidden (which would otherwise crop the star's outer edge
          on circle-shaped avatars). */}
      {hi && (
        <div className="highlight-star" style={{background: hi}} title="Highlight">
          <window.TourIcon name="star-fill" size={10} stroke="#fff" fill="#fff"/>
        </div>
      )}
      {(node.name || node.subtitle) ? (
        <div className={`labels${node.labelPos && node.labelPos !== 'bottom' ? ' pos-' + node.labelPos : ''}`}>
          {node.name ? <div className="name">{node.name}</div> : null}
          {node.subtitle ? <div className="subtitle">{node.subtitle}</div> : null}
        </div>
      ) : null}
      {/* Delete badge — only the × button remains (manual + connector
          was removed since edges are now auto-managed from times). */}
      <div
        className="delete-btn"
        onClick={(e)=>{e.stopPropagation(); onDelete(node.id);}}
        title="Delete"
      >
        {window.TourIcon ? <window.TourIcon name="x" size={12} stroke="currentColor" strokeWidth={3}/> : '×'}
      </div>
    </div>
  );
}

// Convert a hex color #RRGGBB to rgba(...) with given alpha.
function hexAlpha(hex, alpha){
  const m = /^#?([0-9a-f]{6})$/i.exec(hex || '');
  if (!m) return hex;
  const r = parseInt(m[1].slice(0,2),16);
  const g = parseInt(m[1].slice(2,4),16);
  const b = parseInt(m[1].slice(4,6),16);
  return `rgba(${r},${g},${b},${alpha})`;
}

function contrastInk(bg){
  if (!bg) return '#1F2937';
  const m = bg.match(/^#([0-9a-f]{6})$/i);
  if (!m) return '#1F2937';
  const r = parseInt(m[1].slice(0,2),16);
  const g = parseInt(m[1].slice(2,4),16);
  const b = parseInt(m[1].slice(4,6),16);
  const L = (0.299*r+0.587*g+0.114*b)/255;
  return L>0.6 ? '#1F2937' : '#fff';
}

window.Node = Node;
window.contrastInk = contrastInk;
