// Shared comment system for wireframe pages
// Requires: React 18+, Babel standalone (for JSX)
// Backend: /api/comments (Cloudflare Pages Function in functions/api/comments.js)

const { useState: _csUseState, useEffect: _csUseEffect, useRef: _csUseRef, useCallback: _csUseCallback } = React;

// ═══════════════════════════════════════════════════════════════
// useComments hook
// ═══════════════════════════════════════════════════════════════

function useComments(pageId) {
  const [comments, setComments] = _csUseState([]);
  const [commentMode, setCommentMode] = _csUseState(false);
  const [activeThread, setActiveThread] = _csUseState(null);
  const [authorName, setAuthorName] = _csUseState(
    () => localStorage.getItem('__comment_author') || ''
  );

  // Load from localStorage on mount
  _csUseEffect(() => {
    try {
      const stored = localStorage.getItem('__comments_' + pageId);
      if (stored) setComments(JSON.parse(stored));
    } catch (e) {}
  }, [pageId]);

  // Persist to localStorage on change
  _csUseEffect(() => {
    localStorage.setItem('__comments_' + pageId, JSON.stringify(comments));
  }, [comments, pageId]);

  // Persist author name
  _csUseEffect(() => {
    if (authorName) localStorage.setItem('__comment_author', authorName);
  }, [authorName]);

  // API sync (attempts fetch, falls back silently to localStorage-only)
  _csUseEffect(() => {
    const fetchComments = async () => {
      try {
        const res = await fetch('/api/comments?page=' + encodeURIComponent(pageId));
        if (res.ok) {
          const data = await res.json();
          if (data.comments && data.comments.length) {
            setComments(prev => mergeComments(prev, data.comments));
          }
        }
      } catch (e) {}
    };
    fetchComments();
    const interval = setInterval(fetchComments, 15000);
    return () => clearInterval(interval);
  }, [pageId]);

  function mergeComments(local, remote) {
    const map = {};
    local.forEach(c => { map[c.id] = c; });
    remote.forEach(c => {
      const existing = map[c.id];
      if (!existing) { map[c.id] = c; }
      else if (c.messages.length > existing.messages.length) { map[c.id] = c; }
      else if (c.resolved !== existing.resolved && c.resolvedAt > (existing.resolvedAt || '')) { map[c.id] = c; }
    });
    return Object.values(map).sort((a, b) => a.createdAt < b.createdAt ? -1 : 1);
  }

  const needsSyncRef = _csUseRef(false);

  _csUseEffect(() => {
    if (!needsSyncRef.current) return;
    needsSyncRef.current = false;
    fetch('/api/comments', {
      method: 'POST',
      headers: { 'Content-Type': 'application/json' },
      body: JSON.stringify({ page: pageId, comments: comments })
    }).catch(() => {});
  }, [comments, pageId]);

  function markDirty() { needsSyncRef.current = true; }

  const placeComment = _csUseCallback((tabId, xPct, yPct) => {
    const id = 'c_' + Date.now() + '_' + Math.random().toString(36).slice(2, 8);
    const newComment = {
      id, tabId, xPct, yPct,
      messages: [],
      resolved: false,
      resolvedAt: null,
      createdAt: new Date().toISOString()
    };
    setComments(prev => { markDirty(); return [...prev, newComment]; });
    setActiveThread(id);
    setCommentMode(false);
  }, [pageId]);

  const addMessage = _csUseCallback((commentId, text) => {
    if (!text.trim()) return;
    const msg = {
      id: 'm_' + Date.now() + '_' + Math.random().toString(36).slice(2, 8),
      author: authorName || 'Anonymous',
      text: text.trim(),
      timestamp: new Date().toISOString()
    };
    setComments(prev => {
      markDirty();
      return prev.map(c => c.id === commentId ? { ...c, messages: [...c.messages, msg] } : c);
    });
  }, [authorName, pageId]);

  const resolveComment = _csUseCallback((commentId) => {
    setComments(prev => {
      markDirty();
      return prev.map(c => c.id === commentId ? { ...c, resolved: !c.resolved, resolvedAt: new Date().toISOString() } : c);
    });
  }, [pageId]);

  const deleteComment = _csUseCallback((commentId) => {
    setComments(prev => { markDirty(); return prev.filter(c => c.id !== commentId); });
    setActiveThread(null);
  }, [pageId]);

  return {
    items: comments,
    commentMode,
    activeThread,
    authorName,
    unresolvedCount: comments.filter(c => !c.resolved).length,
    toggleCommentMode: () => { setCommentMode(m => !m); setActiveThread(null); },
    selectThread: (id) => { setActiveThread(id === activeThread ? null : id); setCommentMode(false); },
    closeThread: () => setActiveThread(null),
    placeComment,
    addMessage,
    resolveComment,
    deleteComment,
    setAuthorName
  };
}

// ─── Comment Pin ─────────────────────────────────────────────
function CommentPin({ number, x, y, active, resolved, onClick }) {
  return (
    <div
      onClick={(e) => { e.stopPropagation(); onClick(); }}
      style={{
        position: 'absolute',
        left: x + '%', top: y + '%',
        transform: 'translate(-50%, -50%)',
        width: 28, height: 28,
        borderRadius: '50% 48% 52% 50% / 48% 52% 50% 48%',
        background: active ? 'var(--red-soft)' : resolved ? 'var(--paper-2)' : 'var(--red-soft)',
        border: active ? '2.5px solid var(--red)' : resolved ? '1.5px dashed var(--ink-faint)' : '2px solid var(--red)',
        display: 'flex', alignItems: 'center', justifyContent: 'center',
        fontFamily: 'Helvetica, Arial, sans-serif',
        fontSize: 12, fontWeight: 700,
        color: resolved ? 'var(--ink-faint)' : 'var(--ink)',
        cursor: 'pointer',
        boxShadow: active ? '3px 3px 0 rgba(26,24,20,0.25)' : 'var(--shadow)',
        zIndex: active ? 1001 : 1000,
        opacity: resolved ? 0.5 : 1,
        transition: 'transform 100ms, box-shadow 100ms',
        pointerEvents: 'auto'
      }}
      onMouseEnter={(e) => { e.currentTarget.style.transform = 'translate(-50%, -50%) scale(1.15)'; }}
      onMouseLeave={(e) => { e.currentTarget.style.transform = 'translate(-50%, -50%)'; }}
    >
      {number}
    </div>
  );
}

// ─── Comment Thread Popover ──────────────────────────────────
function CommentThread({ comment, number, onAddMessage, onResolve, onDelete, onClose, authorName, onAuthorChange }) {
  const [text, setText] = _csUseState('');
  const messagesRef = _csUseRef(null);

  _csUseEffect(() => {
    if (messagesRef.current) messagesRef.current.scrollTop = messagesRef.current.scrollHeight;
  }, [comment.messages.length]);

  _csUseEffect(() => {
    const handler = (e) => { if (e.key === 'Escape') onClose(); };
    window.addEventListener('keydown', handler);
    return () => window.removeEventListener('keydown', handler);
  }, [onClose]);

  const submit = () => {
    if (!text.trim()) return;
    onAddMessage(comment.id, text);
    setText('');
    onClose();
  };

  return (
    <div style={{
      position: 'absolute',
      left: comment.xPct < 75 ? 'calc(100% + 12px)' : 'auto',
      right: comment.xPct >= 75 ? 'calc(100% + 12px)' : 'auto',
      top: 0, width: 280,
      background: 'var(--paper)',
      border: '2px solid var(--ink)',
      borderRadius: '6px 8px 5px 9px / 8px 5px 9px 6px',
      boxShadow: '3px 3px 0 rgba(26,24,20,0.18)',
      zIndex: 1002,
      fontFamily: 'Helvetica, Arial, sans-serif',
      fontSize: 13, overflow: 'hidden',
      pointerEvents: 'auto'
    }} onClick={(e) => e.stopPropagation()}>
      {/* Header */}
      <div style={{
        display: 'flex', justifyContent: 'space-between', alignItems: 'center',
        padding: '8px 10px', borderBottom: '1.5px solid var(--paper-line)',
        background: 'var(--paper-2)'
      }}>
        <span style={{ fontWeight: 700, fontSize: 13 }}>Comment #{number}</span>
        <div style={{ display: 'flex', gap: 6 }}>
          <button onClick={() => onResolve(comment.id)} style={{
            background: comment.resolved ? 'var(--accent-soft)' : 'var(--green-soft)',
            border: '1.2px solid var(--ink)',
            borderRadius: '3px 5px 3px 6px',
            padding: '2px 8px', fontSize: 10, fontWeight: 700, cursor: 'pointer',
            textTransform: 'uppercase', letterSpacing: '0.4px'
          }}>
            {comment.resolved ? 'Reopen' : 'Resolve'}
          </button>
          <button onClick={() => onDelete(comment.id)} style={{
            background: 'var(--red-soft)',
            border: '1.2px solid var(--ink)',
            borderRadius: '3px 5px 3px 6px',
            padding: '2px 8px', fontSize: 10, fontWeight: 700, cursor: 'pointer',
            textTransform: 'uppercase', letterSpacing: '0.4px'
          }}>
            Delete
          </button>
          <button onClick={onClose} style={{
            background: 'transparent', border: 'none', cursor: 'pointer',
            fontSize: 16, color: 'var(--ink-soft)', padding: '0 2px'
          }}>×</button>
        </div>
      </div>

      {/* Messages */}
      <div ref={messagesRef} style={{ maxHeight: 220, overflowY: 'auto', padding: '6px 10px' }}>
        {comment.messages.length === 0 && (
          <div style={{ color: 'var(--ink-faint)', fontStyle: 'italic', padding: '8px 0', fontSize: 12 }}>
            No messages yet — add the first comment below.
          </div>
        )}
        {comment.messages.map((msg) => (
          <div key={msg.id} style={{ padding: '6px 0', borderBottom: '1px solid var(--paper-line)' }}>
            <div style={{ display: 'flex', justifyContent: 'space-between', marginBottom: 2 }}>
              <span style={{ fontWeight: 700, fontSize: 12 }}>{msg.author}</span>
              <span style={{ fontSize: 10, color: 'var(--ink-faint)' }}>
                {new Date(msg.timestamp).toLocaleString([], { month: 'short', day: 'numeric', hour: '2-digit', minute: '2-digit' })}
              </span>
            </div>
            <div style={{ lineHeight: 1.4, fontSize: 13, whiteSpace: 'pre-wrap' }}>{msg.text}</div>
          </div>
        ))}
      </div>

      {/* Input */}
      <div style={{ borderTop: '1.5px solid var(--paper-line)', padding: '8px 10px' }}>
        <input
          type="text" placeholder="Your name"
          value={authorName}
          onChange={(e) => onAuthorChange(e.target.value)}
          style={{
            width: '100%', marginBottom: 6, padding: '4px 8px',
            border: '1.2px solid var(--ink-soft)',
            borderRadius: '3px 5px 3px 5px',
            background: 'var(--paper)', fontFamily: 'Helvetica, Arial, sans-serif',
            fontSize: 12, outline: 'none'
          }}
        />
        <div style={{ display: 'flex', gap: 6 }}>
          <textarea
            placeholder="Add a comment..."
            value={text}
            onChange={(e) => setText(e.target.value)}
            onKeyDown={(e) => { if (e.key === 'Enter' && !e.shiftKey) { e.preventDefault(); submit(); } }}
            rows={2}
            style={{
              flex: 1, padding: '6px 8px', resize: 'vertical',
              border: '1.5px solid var(--ink-soft)',
              borderRadius: '4px 6px 3px 7px / 6px 3px 7px 4px',
              background: 'var(--paper)', fontFamily: 'Helvetica, Arial, sans-serif',
              fontSize: 13, lineHeight: 1.35, outline: 'none'
            }}
          />
          <button onClick={submit} style={{
            alignSelf: 'flex-end',
            background: 'var(--accent)', border: '1.5px solid var(--ink)',
            borderRadius: '4px 7px 4px 8px / 7px 4px 8px 4px',
            padding: '6px 12px', fontFamily: 'Helvetica, Arial, sans-serif',
            fontWeight: 600, fontSize: 12, cursor: 'pointer',
            boxShadow: '1.5px 1.5px 0 var(--ink)'
          }}>
            Send
          </button>
        </div>
      </div>
    </div>
  );
}

// ─── Comment Layer ───────────────────────────────────────────
function CommentLayer({ comments, activeTab, commentMode, activeThread, onPlaceComment, onSelectThread, onCloseThread, onAddMessage, onResolve, onDelete, authorName, onAuthorChange }) {
  const layerRef = _csUseRef(null);

  const handleClick = (e) => {
    if (!commentMode) return;
    const rect = layerRef.current.getBoundingClientRect();
    const xPct = ((e.clientX - rect.left) / rect.width) * 100;
    const yPct = ((e.clientY - rect.top) / rect.height) * 100;
    onPlaceComment(activeTab, Math.round(xPct * 100) / 100, Math.round(yPct * 100) / 100);
  };

  const tabComments = activeTab
    ? comments.filter(c => c.tabId === activeTab)
    : comments;
  let pinNumber = 0;

  return (
    <div
      ref={layerRef}
      data-comment-layer
      onClick={handleClick}
      style={{
        position: 'absolute',
        inset: 0,
        zIndex: 999,
        cursor: commentMode ? 'crosshair' : 'default',
        pointerEvents: commentMode ? 'auto' : 'none'
      }}
    >
      {tabComments.map((c) => {
        pinNumber++;
        const isActive = activeThread === c.id;
        return (
          <div key={c.id} style={{ position: 'absolute', left: c.xPct + '%', top: c.yPct + '%' }}>
            <CommentPin
              number={pinNumber}
              x={0} y={0}
              active={isActive}
              resolved={c.resolved}
              onClick={() => onSelectThread(c.id)}
            />
            {isActive && (
              <CommentThread
                comment={c}
                number={pinNumber}
                onAddMessage={onAddMessage}
                onResolve={onResolve}
                onDelete={onDelete}
                onClose={onCloseThread}
                authorName={authorName}
                onAuthorChange={onAuthorChange}
              />
            )}
          </div>
        );
      })}
    </div>
  );
}

// ─── Comment Toggle Button ───────────────────────────────────
function CommentToggle({ active, count, onToggle }) {
  return (
    <div style={{ position: 'fixed', bottom: 16, left: 16, zIndex: 10001, display: 'flex', flexDirection: 'column', alignItems: 'flex-start', gap: 8 }}>
      <button
        onClick={onToggle}
        style={{
          width: 44, height: 44,
          background: active ? 'var(--accent)' : 'var(--paper)',
          border: '2px solid var(--ink)',
          borderRadius: '8px 10px 7px 11px / 10px 7px 11px 8px',
          boxShadow: active ? '3px 3px 0 var(--ink)' : 'var(--shadow)',
          cursor: 'pointer',
          display: 'flex', alignItems: 'center', justifyContent: 'center',
          position: 'relative',
          transition: 'transform 80ms, box-shadow 80ms'
        }}
        onMouseEnter={(e) => { e.currentTarget.style.transform = 'translate(-1px, -1px)'; }}
        onMouseLeave={(e) => { e.currentTarget.style.transform = ''; }}
      >
        <svg width="22" height="22" viewBox="0 0 24 24" fill="none" stroke="var(--ink)" strokeWidth="2" strokeLinecap="round" strokeLinejoin="round">
          <path d="M21 15a2 2 0 0 1-2 2H7l-4 4V5a2 2 0 0 1 2-2h14a2 2 0 0 1 2 2z" />
        </svg>
        {count > 0 && (
          <div style={{
            position: 'absolute', top: -6, right: -6,
            width: 18, height: 18, borderRadius: '50%',
            background: 'var(--red)', color: '#fff',
            fontSize: 10, fontWeight: 700,
            display: 'flex', alignItems: 'center', justifyContent: 'center',
            border: '1.5px solid var(--paper)',
            fontFamily: 'Helvetica, Arial, sans-serif'
          }}>{count}</div>
        )}
      </button>
      {active && (
        <div style={{
          background: 'var(--accent-soft)',
          border: '1.5px solid var(--ink)',
          borderRadius: '4px 8px 5px 7px / 7px 5px 8px 4px',
          padding: '6px 12px',
          fontFamily: 'Helvetica, Arial, sans-serif',
          fontSize: 12, fontWeight: 600,
          boxShadow: 'var(--shadow)',
          whiteSpace: 'nowrap'
        }}>
          Click anywhere to leave a comment
        </div>
      )}
    </div>
  );
}
