// Screen: MAP TỔNG / Workflow canvas
// Drag nodes freely. Drag from output port to input port of another node to connect.
// Drag library items onto canvas to create new nodes.

const ScreenMap = ({ mapState, onUpdateMap }) => {
  const { nodes, edges, selectedId } = mapState;
  const stageRef = React.useRef(null);
  const [dragging, setDragging] = React.useState(null);  // {id, offsetX, offsetY}
  const [drawing, setDrawing] = React.useState(null);    // {fromId, fromSide, x, y}
  const [hoverPort, setHoverPort] = React.useState(null);// {id, side}
  const [mouse, setMouse] = React.useState({ x: 0, y: 0 });
  const [optPrompt, setOptPrompt] = React.useState(
    'Tối ưu cho ROAS > 3.5 trong 7 ngày. Ưu tiên persona Linh Minh & Tuấn Anh. Push creative angle "agency replacement".'
  );

  // Stable references for handlers
  const stageRect = () => stageRef.current && stageRef.current.getBoundingClientRect();

  const onMouseMove = (e) => {
    const rect = stageRect();
    if (!rect) return;
    const x = e.clientX - rect.left;
    const y = e.clientY - rect.top;
    setMouse({ x, y });
    if (dragging) {
      onUpdateMap({
        nodes: nodes.map(n => n.id === dragging.id
          ? { ...n, x: x - dragging.offsetX, y: y - dragging.offsetY }
          : n
        ),
      });
    } else if (drawing) {
      setDrawing(d => ({ ...d, x, y }));
    }
  };

  const onMouseUp = () => {
    if (drawing && hoverPort && hoverPort.id !== drawing.fromId) {
      // create edge
      const exists = edges.some(e =>
        (e.from === drawing.fromId && e.to === hoverPort.id) ||
        (e.from === hoverPort.id && e.to === drawing.fromId));
      if (!exists) {
        const from = drawing.fromSide === 'out' ? drawing.fromId : hoverPort.id;
        const to   = drawing.fromSide === 'out' ? hoverPort.id   : drawing.fromId;
        onUpdateMap({
          edges: [...edges, { id: `e-${Date.now()}`, from, to }],
        });
      }
    }
    setDragging(null);
    setDrawing(null);
  };

  const onNodeMouseDown = (e, node) => {
    if (e.target.closest('.map-port')) return;
    e.stopPropagation();
    const rect = stageRect();
    onUpdateMap({ selectedId: node.id });
    setDragging({
      id: node.id,
      offsetX: e.clientX - rect.left - node.x,
      offsetY: e.clientY - rect.top - node.y,
    });
  };

  const onPortMouseDown = (e, node, side) => {
    e.stopPropagation();
    const rect = stageRect();
    setDrawing({
      fromId: node.id,
      fromSide: side,
      x: e.clientX - rect.left,
      y: e.clientY - rect.top,
    });
  };

  const onStageMouseDown = (e) => {
    if (e.target === stageRef.current || e.target.classList.contains('canvas-bg')) {
      onUpdateMap({ selectedId: null });
    }
  };

  // Drop from library
  const onDrop = (e) => {
    e.preventDefault();
    const kind = e.dataTransfer.getData('flow/kind');
    const label = e.dataTransfer.getData('flow/label');
    const sub = e.dataTransfer.getData('flow/sub');
    if (!kind) return;
    const rect = stageRect();
    const x = e.clientX - rect.left - 110;
    const y = e.clientY - rect.top - 35;
    const newNode = {
      id: `n-${Date.now()}`, kind, x, y,
      title: label, sub: sub || '—', meta: `${kind} · added`,
    };
    onUpdateMap({ nodes: [...nodes, newNode], selectedId: newNode.id });
  };

  // Delete selected on Backspace
  React.useEffect(() => {
    const h = (e) => {
      if ((e.key === 'Backspace' || e.key === 'Delete') && selectedId && document.activeElement.tagName !== 'INPUT' && document.activeElement.tagName !== 'TEXTAREA') {
        e.preventDefault();
        onUpdateMap({
          nodes: nodes.filter(n => n.id !== selectedId),
          edges: edges.filter(e => e.from !== selectedId && e.to !== selectedId),
          selectedId: null,
        });
      }
    };
    window.addEventListener('keydown', h);
    return () => window.removeEventListener('keydown', h);
  }, [selectedId, nodes, edges]);

  const portPos = (node, side) => {
    const w = node.kind === 'result' ? 270 : 220;
    return {
      x: node.x + (side === 'out' ? w : 0),
      y: node.y + (node.kind === 'result' ? 60 : 50),
    };
  };

  const bezier = (x1, y1, x2, y2) => {
    const dx = Math.max(50, Math.abs(x2 - x1) * 0.5);
    return `M ${x1} ${y1} C ${x1 + dx} ${y1}, ${x2 - dx} ${y2}, ${x2} ${y2}`;
  };

  const selectedNode = nodes.find(n => n.id === selectedId);

  return (
    <div className="screen-body" style={{ gridTemplateColumns: '240px 1fr' }} data-screen-label="05 Map tổng">
      {/* Library */}
      <div className="map-library">
        <div className="map-library-head">
          <span className="title">Saved files</span>
          <span className="sub">Kéo thả vào canvas để dùng</span>
        </div>
        <div style={{ overflowY: 'auto', flex: 1 }}>
          {['product', 'persona', 'content', 'ads', 'data'].map(kind => {
            const items = MAP_LIBRARY.filter(l => l.kind === kind);
            const conf = NODE_KIND[kind];
            const labels = {
              product: 'Sản phẩm',
              persona: 'Chân dung KH',
              content: 'Content plans',
              ads:     'Digital Ads',
              data:    'Ads data (CSV)',
            };
            return (
              <div className="map-library-section" key={kind}>
                <div className="map-library-section-label">
                  <span style={{ color: conf.accent }}>● </span>{labels[kind]}
                </div>
                {items.map(item => (
                  <div
                    key={item.id}
                    className="map-library-item"
                    draggable
                    onDragStart={(e) => {
                      e.dataTransfer.setData('flow/kind', item.kind);
                      e.dataTransfer.setData('flow/label', item.label);
                      e.dataTransfer.setData('flow/sub', item.sub);
                      e.dataTransfer.effectAllowed = 'copy';
                    }}
                  >
                    <div className="map-library-item-icon" style={{ background: conf.bg, color: conf.accent }}>
                      <Icon name={conf.icon} size={13} />
                    </div>
                    <div className="map-library-item-meta">
                      <span className="map-library-item-title">{item.label}</span>
                      <span className="map-library-item-sub">{item.sub}</span>
                    </div>
                  </div>
                ))}
              </div>
            );
          })}
        </div>
      </div>

      {/* Stage */}
      <div
        ref={stageRef}
        className="map-stage canvas-bg"
        onMouseMove={onMouseMove}
        onMouseUp={onMouseUp}
        onMouseDown={onStageMouseDown}
        onDragOver={(e) => e.preventDefault()}
        onDrop={onDrop}
      >
        {/* Top right: Run */}
        <div className="map-run">
          <div className="map-prompt-bar">
            <Icon name="sparkles" size={12} color="var(--accent-cyan)" />
            <input
              placeholder="Optimization prompt cho output cuối…"
              value={optPrompt}
              onChange={(e) => setOptPrompt(e.target.value)}
            />
          </div>
          <Btn variant="accent" size="md" icon="play">Run workflow</Btn>
        </div>

        {/* SVG layer for connectors */}
        <svg
          width="100%" height="100%"
          style={{ position: 'absolute', inset: 0, pointerEvents: 'none', overflow: 'visible' }}
        >
          <defs>
            <marker id="arrow" viewBox="0 0 10 10" refX="9" refY="5"
              markerWidth="7" markerHeight="7" orient="auto">
              <path d="M 0 0 L 10 5 L 0 10 z" fill="var(--accent-cyan)" />
            </marker>
          </defs>
          {edges.map(edge => {
            const from = nodes.find(n => n.id === edge.from);
            const to   = nodes.find(n => n.id === edge.to);
            if (!from || !to) return null;
            const a = portPos(from, 'out');
            const b = portPos(to, 'in');
            return (
              <path
                key={edge.id}
                d={bezier(a.x, a.y, b.x, b.y)}
                fill="none"
                stroke={edge.to === selectedId || edge.from === selectedId ? 'var(--accent-cyan)' : 'var(--accent-cyan-dim, #45A29E)'}
                strokeWidth="2"
                markerEnd="url(#arrow)"
                style={{
                  filter: edge.to === selectedId || edge.from === selectedId
                    ? 'drop-shadow(0 0 4px rgba(102,252,241,0.4))'
                    : 'none',
                }}
              />
            );
          })}
          {drawing && (() => {
            const from = nodes.find(n => n.id === drawing.fromId);
            if (!from) return null;
            const a = portPos(from, drawing.fromSide);
            return (
              <path
                d={bezier(
                  drawing.fromSide === 'out' ? a.x : mouse.x,
                  drawing.fromSide === 'out' ? a.y : mouse.y,
                  drawing.fromSide === 'out' ? mouse.x : a.x,
                  drawing.fromSide === 'out' ? mouse.y : a.y,
                )}
                fill="none"
                stroke="var(--accent-cyan)"
                strokeWidth="2"
                strokeDasharray="5 4"
              />
            );
          })()}
        </svg>

        {/* Nodes */}
        {nodes.map(node => (
          <MapNode
            key={node.id}
            node={node}
            selected={node.id === selectedId}
            onMouseDown={(e) => onNodeMouseDown(e, node)}
            onPortMouseDown={onPortMouseDown}
            onPortEnter={(side) => setHoverPort({ id: node.id, side })}
            onPortLeave={() => setHoverPort(null)}
            hoverPort={hoverPort}
          />
        ))}

        {nodes.length === 0 && (
          <div className="map-empty">
            <div className="big">Canvas trống</div>
            <div className="sub">Kéo saved file từ sidebar trái để bắt đầu</div>
          </div>
        )}

        {/* Selected node detail */}
        {selectedNode && (
          <div className="node-detail-panel">
            <div style={{
              display: 'flex', alignItems: 'center', gap: 8, marginBottom: 6,
            }}>
              <span style={{
                width: 22, height: 22, borderRadius: 5,
                background: NODE_KIND[selectedNode.kind].bg,
                color: NODE_KIND[selectedNode.kind].accent,
                display: 'flex', alignItems: 'center', justifyContent: 'center',
              }}>
                <Icon name={NODE_KIND[selectedNode.kind].icon} size={13} />
              </span>
              <h5 style={{ margin: 0, flex: 1, fontSize: 13 }}>{selectedNode.title}</h5>
            </div>
            <div style={{ fontSize: 11.5, color: 'var(--fg-secondary)', lineHeight: 1.5, marginBottom: 8 }}>
              {selectedNode.sub}
            </div>
            <div style={{ fontFamily: 'var(--font-mono)', fontSize: 10, color: 'var(--fg-muted)', letterSpacing: '0.06em' }}>
              {selectedNode.meta}
            </div>

            {selectedNode.kind !== 'result' && (
              <div className="node-config-field">
                <span className="node-config-label">AI Model</span>
                <select
                  className="node-config-select"
                  value={selectedNode.model || 'claude-sonnet-4.5'}
                  onChange={(e) => onUpdateMap({
                    nodes: nodes.map(n => n.id === selectedId ? { ...n, model: e.target.value } : n),
                  })}
                >
                  {AI_MODELS.map(m => <option key={m.id} value={m.id}>{m.label}</option>)}
                </select>
              </div>
            )}

            <div className="node-config-field">
              <span className="node-config-label">Style</span>
              <div className="node-config-tags">
                {STYLE_PRESETS.filter(s => s.id !== 'custom').map(s => (
                  <button
                    key={s.id}
                    className={`node-config-mini-pill ${(selectedNode.styleId || 'analytical') === s.id ? 'active' : ''}`}
                    onClick={() => onUpdateMap({
                      nodes: nodes.map(n => n.id === selectedId ? { ...n, styleId: s.id } : n),
                    })}
                  >{s.label}</button>
                ))}
              </div>
            </div>

            <div className="node-config-field">
              <span className="node-config-label">Prompt overlay cho node</span>
              <textarea
                className="node-config-textarea"
                value={selectedNode.prompt || ''}
                placeholder="Thêm prompt riêng cho node này (ưu tiên hơn style preset)…"
                onChange={(e) => onUpdateMap({
                  nodes: nodes.map(n => n.id === selectedId ? { ...n, prompt: e.target.value } : n),
                })}
              />
            </div>

            <div className="btn-row" style={{ justifyContent: 'space-between', marginTop: 14 }}>
              <Btn variant="ghost" size="sm" icon="external-link">Mở file</Btn>
              <div className="btn-row">
                <Btn variant="primary" size="sm" icon="play">Re-run</Btn>
                <Btn
                  variant="danger" size="sm" icon="trash-2"
                  onClick={() => onUpdateMap({
                    nodes: nodes.filter(n => n.id !== selectedId),
                    edges: edges.filter(e => e.from !== selectedId && e.to !== selectedId),
                    selectedId: null,
                  })}
                />
              </div>
            </div>
          </div>
        )}

        {/* Bottom right zoom controls */}
        <div className="map-controls">
          <button title="Zoom out"><Icon name="minus" size={14} /></button>
          <span className="zoom-val">100%</span>
          <button title="Zoom in"><Icon name="plus" size={14} /></button>
          <span style={{ width: 1, height: 18, background: 'var(--border)' }} />
          <button title="Fit"><Icon name="maximize" size={14} /></button>
          <button title="Toggle grid"><Icon name="grid-3x3" size={14} /></button>
          <span style={{ width: 1, height: 18, background: 'var(--border)' }} />
          <span className="zoom-val" style={{ minWidth: 'auto', padding: '0 6px' }}>
            {nodes.length} nodes · {edges.length} links
          </span>
        </div>
      </div>
    </div>
  );
};

// ── Node renderer ────────────────────────────────────────
const MapNode = ({ node, selected, onMouseDown, onPortMouseDown, onPortEnter, onPortLeave, hoverPort }) => {
  const conf = NODE_KIND[node.kind];
  const isResult = node.kind === 'result';

  return (
    <div
      className={`map-node ${selected ? 'selected' : ''} ${isResult ? 'result' : ''}`}
      style={{ left: node.x, top: node.y }}
      onMouseDown={onMouseDown}
    >
      <div className="map-node-head" style={isResult ? null : { background: conf.bg }}>
        <div className="map-node-icon" style={{ background: conf.bg, color: conf.accent }}>
          <Icon name={conf.icon} size={13} />
        </div>
        <span className="map-node-title">{node.title}</span>
        {node.model && (
          <span
            className="map-node-ai-badge"
            title={`AI: ${node.model}`}
          >
            {(AI_MODELS.find(m => m.id === node.model) || {}).label?.replace(/Claude |Gemini |DeepSeek |GPT /,'') || 'AI'}
          </span>
        )}
        <span className="map-node-pill" style={{ background: conf.bg, color: conf.accent }}>
          {conf.label}
        </span>
      </div>

      {isResult ? (
        <div className="map-result-grid">
          {Object.entries(node.result).map(([key, m]) => (
            <div className="map-result-cell" key={key}>
              <span className="label">{key === 'cpl' ? 'CPL' : key === 'ctr' ? 'CTR' : key}</span>
              <span className={`val ${m.flavor || ''}`}>
                {m.val}<span className="unit"> {m.unit}</span>
              </span>
            </div>
          ))}
        </div>
      ) : (
        <div className="map-node-body">{node.sub}</div>
      )}

      <div className="map-node-foot">
        <span>{node.meta}</span>
        {isResult
          ? <Badge label="Live" color="var(--accent-cyan)" bg="rgba(102,252,241,0.10)" pulse />
          : <span style={{ display: 'flex', alignItems: 'center', gap: 4 }}>
              <Icon name="circle-check" size={10} color="var(--success)" />
              <span style={{ color: 'var(--success)', fontFamily: 'var(--font-mono)', fontSize: 9.5 }}>SAVED</span>
            </span>
        }
      </div>

      {/* Ports */}
      {!isResult || node.kind === 'result' ? (
        <React.Fragment>
          <div
            className={`map-port in ${hoverPort && hoverPort.id === node.id && hoverPort.side === 'in' ? 'armed' : ''}`}
            onMouseDown={(e) => onPortMouseDown(e, node, 'in')}
            onMouseEnter={() => onPortEnter('in')}
            onMouseLeave={onPortLeave}
          />
          {!isResult && (
            <div
              className={`map-port out ${hoverPort && hoverPort.id === node.id && hoverPort.side === 'out' ? 'armed' : ''}`}
              onMouseDown={(e) => onPortMouseDown(e, node, 'out')}
              onMouseEnter={() => onPortEnter('out')}
              onMouseLeave={onPortLeave}
            />
          )}
        </React.Fragment>
      ) : null}
    </div>
  );
};

Object.assign(window, { ScreenMap });
