/* ============================================================
   blocks.jsx — renders document blocks on canvas
   ============================================================ */

function InlineText({ blockId, field, value, onChange, tag = 'span', className, placeholder, multiline = false }) {
  const ref = useRef(null);
  const { doc, activeCommentId, setActiveCommentId } = useApp();

  // render text with comment/suggestion highlights
  const renderHighlighted = () => {
    const comments = doc.comments.filter(c => c.blockId === blockId && !c.resolved && c.range?.field === field);
    const sugs = doc.suggestions.filter(s => s.blockId === blockId && s.status === 'pending' && s.range?.field === field);
    if (comments.length === 0 && sugs.length === 0) return value;

    // build marker list
    const marks = [];
    comments.forEach(c => marks.push({ start: c.range.start, end: c.range.end, kind: 'comment', id: c.id }));
    sugs.forEach(s => marks.push({ start: s.range.start, end: s.range.end, kind: 'suggestion', id: s.id, proposed: s.proposed }));
    marks.sort((a,b) => a.start - b.start);

    const out = [];
    let cursor = 0;
    marks.forEach((m, i) => {
      if (m.start > cursor) out.push(value.slice(cursor, m.start));
      const chunk = value.slice(m.start, m.end);
      if (m.kind === 'comment') {
        out.push(<span key={i} className={'has-comment' + (activeCommentId === m.id ? ' active' : '')}
          onClick={(e)=>{ e.stopPropagation(); setActiveCommentId(m.id); }}>{chunk}</span>);
      } else {
        out.push(
          <span key={i} onClick={(e)=>{ e.stopPropagation(); setActiveCommentId(m.id); }}>
            <span className="suggestion-del">{chunk}</span>
            <span className="suggestion-ins">{m.proposed}</span>
          </span>
        );
      }
      cursor = m.end;
    });
    if (cursor < value.length) out.push(value.slice(cursor));
    return out;
  };

  const Tag = tag;
  // editable via double-click only when no highlights exist, for simplicity:
  const [editing, setEditing] = useState(false);
  const handleBlur = (e) => { setEditing(false); onChange(e.target.value); };
  const handleKey = (e) => {
    if (!multiline && e.key === 'Enter') { e.preventDefault(); e.target.blur(); }
    if (e.key === 'Escape') e.target.blur();
  };

  if (editing) {
    const InputTag = multiline ? 'textarea' : 'input';
    return <InputTag
      ref={ref}
      className={'inline-edit ' + (className || '')}
      defaultValue={value}
      autoFocus
      onBlur={handleBlur}
      onKeyDown={handleKey}
      rows={multiline ? 3 : undefined}
      style={multiline ? { minHeight: '1.6em' } : undefined}
    />;
  }
  return <Tag className={className} onDoubleClick={() => setEditing(true)} data-block-field={field} data-block-id={blockId}>
    {renderHighlighted()}
  </Tag>;
}

function PhotoCell({ block, index, updateBlock }) {
  const { doc } = useApp();
  const [busy, setBusy] = useState(false);
  const [err, setErr] = useState(null);
  const url = block.urls?.[index];
  const label = block.labels?.[index] || `Afbeelding ${index + 1}`;

  const onFile = async (file) => {
    if (!file) return;
    setBusy(true); setErr(null);
    try {
      const newUrl = await window.uploadAsset(file, { docId: doc.id || 'misc', kind: 'photo' });
      const urls = [...(block.urls || [])];
      urls[index] = newUrl;
      updateBlock(block.id, { urls });
    } catch (e) {
      setErr(e.message || 'Upload mislukt');
    } finally {
      setBusy(false);
    }
  };

  const onRemove = (e) => {
    e.stopPropagation();
    window.deleteAsset?.(url);
    const urls = [...(block.urls || [])];
    urls[index] = null;
    updateBlock(block.id, { urls });
  };

  if (url) {
    return (
      <div className="photo-cell has-image" data-label={label}>
        <img src={url} alt={label} draggable={false}/>
        <button className="photo-remove" onClick={onRemove} title="Verwijderen">×</button>
      </div>
    );
  }

  return (
    <label className={'photo-cell' + (busy ? ' uploading' : '')} data-label={label}>
      <input type="file" accept="image/*" style={{display: 'none'}} disabled={busy}
             onChange={e => onFile(e.target.files?.[0])}/>
      {busy ? <span className="photo-busy">Uploaden…</span> : <I.photos/>}
      {err && <span className="photo-err">{err}</span>}
    </label>
  );
}

function BlockRenderer({ block, index }) {
  const { updateBlock, selectedBlockId, setSelectedBlockId } = useApp();
  const sel = selectedBlockId === block.id;
  const [dragging, setDragging] = useState(false);

  const onSelect = (e) => { e.stopPropagation(); setSelectedBlockId(block.id); };

  const wrap = (content) => (
    <div
      className={'doc-block' + (sel ? ' selected' : '') + (dragging ? ' dragging' : '')}
      data-block-id={block.id}
      onClick={onSelect}
      draggable={false}
    >
      <span
        className="handle"
        title="Sleep om te verplaatsen"
        draggable
        onDragStart={(e) => {
          e.dataTransfer.setData('text/block-move', String(index));
          e.dataTransfer.effectAllowed = 'move';
          setDragging(true);
          window.dispatchEvent(new CustomEvent('tender-drag-start', { detail: { kind: 'move' } }));
        }}
        onDragEnd={() => {
          setDragging(false);
          window.dispatchEvent(new CustomEvent('tender-drag-end'));
        }}
      ><I.drag/></span>
      {content}
    </div>
  );

  switch (block.type) {
    case 'h1': return wrap(<InlineText blockId={block.id} field="text" tag="h1" className="doc-h1"
      value={block.text} onChange={t => updateBlock(block.id, { text: t })} />);
    case 'h2': return wrap(<InlineText blockId={block.id} field="text" tag="h2" className="doc-h2"
      value={block.text} onChange={t => updateBlock(block.id, { text: t })} />);
    case 'h3': return wrap(<InlineText blockId={block.id} field="text" tag="h3" className="doc-h3"
      value={block.text} onChange={t => updateBlock(block.id, { text: t })} />);
    case 'p':  return wrap(<InlineText blockId={block.id} field="text" tag="p" className="doc-p"
      value={block.text} onChange={t => updateBlock(block.id, { text: t })} multiline />);

    case 'numlist': return wrap(
      <ol className={'doc-numlist level-' + (block.level || 1)}>
        {block.items.map((it, i) => (
          <li key={i}>
            <InlineText blockId={block.id} field={`item-${i}`} tag="span" value={it} multiline
              onChange={t => {
                const items = [...block.items]; items[i] = t;
                updateBlock(block.id, { items });
              }} />
          </li>
        ))}
      </ol>
    );

    case 'ul': return wrap(
      <ul className="doc-ul">
        {block.items.map((it, i) => (
          <li key={i}>
            <InlineText blockId={block.id} field={`item-${i}`} tag="span" value={it} multiline
              onChange={t => {
                const items = [...block.items]; items[i] = t;
                updateBlock(block.id, { items });
              }} />
          </li>
        ))}
      </ul>
    );

    case 'callout': return wrap(
      <div className="doc-callout" data-tone={block.tone}>
        <div className="callout-label">
          <svg width="10" height="10" viewBox="0 0 10 10"><circle cx="5" cy="5" r="4" fill="currentColor"/></svg>
          <InlineText blockId={block.id} field="label" tag="span" value={block.label}
            onChange={t => updateBlock(block.id, { label: t })} />
        </div>
        <InlineText blockId={block.id} field="title" tag="div" className="callout-title"
          value={block.title} onChange={t => updateBlock(block.id, { title: t })} />
        <InlineText blockId={block.id} field="body" tag="p" className="callout-body" multiline
          value={block.body} onChange={t => updateBlock(block.id, { body: t })} />
      </div>
    );

    case 'quote': return wrap(
      <div className="doc-quote">
        <blockquote>
          <InlineText blockId={block.id} field="text" tag="span" value={block.text} multiline
            onChange={t => updateBlock(block.id, { text: t })} />
        </blockquote>
        <cite>
          <InlineText blockId={block.id} field="cite" tag="span" value={block.cite}
            onChange={t => updateBlock(block.id, { cite: t })} />
        </cite>
      </div>
    );

    case 'photos': return wrap(
      <div className="doc-photos" data-cols={block.cols}>
        {Array.from({ length: block.cols }).map((_, i) => (
          <PhotoCell key={i} block={block} index={i} updateBlock={updateBlock}/>
        ))}
      </div>
    );

    case 'diagram': return wrap(
      <div className="doc-diagram">
        <DiagramPlaceholder title={block.title}/>
      </div>
    );

    case 'table': return wrap(
      <table className="doc-table">
        <thead><tr>{block.headers.map((h,i) => <th key={i}>{h}</th>)}</tr></thead>
        <tbody>
          {block.rows.map((r,i) => <tr key={i}>{r.map((c,j) => <td key={j}>{c}</td>)}</tr>)}
        </tbody>
      </table>
    );

    case 'kpis': return wrap(
      <div className="doc-kpis">
        {block.items.map((k,i) => (
          <div className="kpi" key={i}>
            <div><span className="kpi-n">{k.n}</span><span className="kpi-unit">{k.unit}</span></div>
            <div className="kpi-label">{k.label}</div>
          </div>
        ))}
      </div>
    );

    case 'pagebreak': return wrap(<hr className="page-break"/>);

    default: return wrap(<div>Onbekend blok</div>);
  }
}

function DiagramPlaceholder({ title }) {
  return (
    <svg viewBox="0 0 600 220" style={{ width: '100%', height: '100%' }}>
      <defs>
        <marker id="arr" viewBox="0 0 10 10" refX="9" refY="5" markerWidth="6" markerHeight="6" orient="auto">
          <path d="M0,0 L10,5 L0,10 z" fill="currentColor" opacity="0.5"/>
        </marker>
      </defs>
      <g fill="none" stroke="currentColor" strokeWidth="1" opacity="0.3">
        <rect x="20"  y="80" width="120" height="60" rx="6"/>
        <rect x="170" y="40" width="120" height="60" rx="6"/>
        <rect x="170" y="120" width="120" height="60" rx="6"/>
        <rect x="320" y="80" width="120" height="60" rx="6"/>
        <rect x="470" y="80" width="110" height="60" rx="6"/>
      </g>
      <g fill="currentColor" fontSize="11" fontFamily="Geist" opacity="0.75">
        <text x="80"  y="115" textAnchor="middle">Intake</text>
        <text x="230" y="75"  textAnchor="middle">Techniek</text>
        <text x="230" y="155" textAnchor="middle">Mensen</text>
        <text x="380" y="115" textAnchor="middle">Ketentest</text>
        <text x="525" y="115" textAnchor="middle">Go-live</text>
      </g>
      <g stroke="currentColor" strokeWidth="1" fill="none" opacity="0.4" markerEnd="url(#arr)">
        <path d="M140,110 L170,70"/>
        <path d="M140,110 L170,150"/>
        <path d="M290,70  L320,110"/>
        <path d="M290,150 L320,110"/>
        <path d="M440,110 L470,110"/>
      </g>
      {title && <text x="20" y="30" fontSize="11" fontFamily="Geist" fontWeight="600" fill="currentColor" opacity="0.9">{title}</text>}
    </svg>
  );
}

Object.assign(window, { BlockRenderer, InlineText });
