/* global React, SectionTitle */
// ============================================================
// Automation Builder — éditeur de graphe de nœuds (style Tampro)
// ============================================================

const AUTO_BLOCKS = {
  "DÉCLENCHEUR": [
    { type: "trigger_manual",   label: "Déclencheur",          color: "#22d3ee", dot: "#22d3ee" },
    { type: "trigger_schedule", label: "Planifié (cron)",       color: "#22d3ee", dot: "#22d3ee" },
    { type: "trigger_webhook",  label: "Webhook entrant",       color: "#22d3ee", dot: "#22d3ee" },
  ],
  "IPHONE (WDA)": [
    { type: "wda_open_app",     label: "Ouvrir app",            color: "#7c5cff", dot: "#7c5cff" },
    { type: "wda_tap_text",     label: "Tap — texte",           color: "#7c5cff", dot: "#7c5cff" },
    { type: "wda_tap_ai",       label: "Tap — IA (description)",color: "#a78bfa", dot: "#a78bfa" },
    { type: "wda_ai_router",    label: "IA Router (voit quoi ?)",color:"#f5b942", dot: "#f5b942" },
    { type: "wda_zones",        label: "Zones calibrées",       color: "#7c5cff", dot: "#7c5cff" },
    { type: "wda_tap_xy",       label: "Tap — X/Y",             color: "#7c5cff", dot: "#7c5cff" },
    { type: "wda_tap_n",        label: "Tap X fois",            color: "#7c5cff", dot: "#7c5cff" },
    { type: "wda_date_picker",  label: "Sélecteur date",        color: "#7c5cff", dot: "#7c5cff" },
    { type: "wda_type",         label: "Saisir texte",          color: "#7c5cff", dot: "#7c5cff" },
    { type: "wda_swipe",        label: "Swipe",                 color: "#7c5cff", dot: "#7c5cff" },
    { type: "wda_long_press",   label: "Long press + glisser",  color: "#7c5cff", dot: "#7c5cff" },
    { type: "wda_wait_el",      label: "Attendre élément",      color: "#7c5cff", dot: "#7c5cff" },
    { type: "wda_home",         label: "Bouton Home",           color: "#7c5cff", dot: "#ec4899" },
    { type: "wda_screenshot",   label: "Screenshot",            color: "#7c5cff", dot: "#7c5cff" },
    { type: "wda_color_check",  label: "Vérif. couleur",        color: "#f5b942", dot: "#f5b942" },
  ],
  "FARM": [
    { type: "farm_rotate_ip",   label: "Rotation IP",           color: "#00e08a", dot: "#00e08a" },
    { type: "farm_buy_sms",     label: "Acheter numéro SMS",    color: "#00e08a", dot: "#ec4899" },
    { type: "farm_switch_sms",  label: "Switch Provider SMS",   color: "#00e08a", dot: "#00e08a" },
    { type: "farm_wait_sms",    label: "Attendre SMS",          color: "#00e08a", dot: "#00e08a" },
    { type: "farm_enter_code",  label: "Saisir code SMS",       color: "#00e08a", dot: "#00e08a" },
    { type: "farm_totp",        label: "Activer 2FA (TOTP)",    color: "#00e08a", dot: "#f5b942" },
    { type: "farm_save_account",label: "Sauvegarder compte",    color: "#00e08a", dot: "#00e08a" },
  ],
  "LOGIQUE": [
    { type: "logic_wait",       label: "Attendre Xs",           color: "#f5b942", dot: "#f5b942" },
    { type: "logic_condition",  label: "Condition si...",        color: "#f5b942", dot: "#f5b942" },
    { type: "logic_loop",       label: "Boucle ×N",             color: "#6366f1", dot: "#6366f1" },
    { type: "logic_random",     label: "Aléatoire",             color: "#f5b942", dot: "#f97316" },
    { type: "logic_merge",      label: "Fusionner",             color: "#6366f1", dot: "#6366f1" },
    { type: "logic_split",      label: "↳ Diviser (tout)",      color: "#6366f1", dot: "#6366f1" },
  ],
};

// champs de config par type
const BLOCK_FIELDS = {
  trigger_schedule: [{ key: "cron", label: "Cron", ph: "0 9 * * *" }],
  trigger_webhook:  [{ key: "path", label: "Chemin", ph: "/hook/mon-auto" }],
  wda_open_app:     [{ key: "bundle", label: "Bundle ID", ph: "com.instagram.Instagram" }],
  wda_tap_text:     [{ key: "text", label: "Texte cible", ph: "Post" }],
  wda_tap_ai:       [{ key: "desc", label: "Description IA", ph: "Bouton bleu en bas à droite" }],
  wda_ai_router:    [{ key: "q", label: "Question IA", ph: "Quel est l'état de la page ?" }],
  wda_tap_xy:       [{ key: "x", label: "X (0-1)", ph: "0.5" }, { key: "y", label: "Y (0-1)", ph: "0.8" }],
  wda_tap_n:        [{ key: "n", label: "Nombre", ph: "3" }, { key: "text", label: "Texte cible", ph: "Like" }],
  wda_swipe:        [{ key: "dir", label: "Direction", type: "select", opts: ["up","down","left","right"] }],
  wda_type:         [{ key: "text", label: "Texte à saisir", ph: "Bonjour !" }],
  wda_wait_el:      [{ key: "text", label: "Élément", ph: "Suivre" }, { key: "timeout", label: "Timeout (s)", ph: "15" }],
  wda_color_check:  [{ key: "x", label: "X", ph: "0.5" }, { key: "y", label: "Y", ph: "0.5" }, { key: "color", label: "Couleur", ph: "#ff0000" }],
  wda_date_picker:  [{ key: "date", label: "Date", ph: "2025-01-01" }],
  wda_long_press:   [{ key: "text", label: "Cible", ph: "Post" }, { key: "dur", label: "Durée (s)", ph: "2" }],
  farm_rotate_ip:   [{ key: "prov", label: "Provider", type: "select", opts: ["auto","airmore","custom"] }],
  farm_buy_sms:     [{ key: "country", label: "Pays", ph: "US" }, { key: "service", label: "Service", ph: "instagram" }],
  farm_wait_sms:    [{ key: "timeout", label: "Timeout (s)", ph: "120" }],
  farm_totp:        [{ key: "secret", label: "Secret TOTP", ph: "JBSWY3DP..." }],
  farm_save_account:[{ key: "label", label: "Label", ph: "ig_compte_01" }],
  logic_wait:       [{ key: "sec", label: "Secondes", ph: "3" }, { key: "rand", label: "±Aléatoire (s)", ph: "1" }],
  logic_condition:  [{ key: "var", label: "Variable", ph: "last_sms" }, { key: "op", label: "Opérateur", type: "select", opts: ["contains","equals","not_empty","empty"] }, { key: "val", label: "Valeur", ph: "confirmé" }],
  logic_loop:       [{ key: "n", label: "Répétitions", ph: "5" }],
  logic_random:     [{ key: "min", label: "Min (s)", ph: "1" }, { key: "max", label: "Max (s)", ph: "5" }],
};

function blockDef(type) {
  for (const blocks of Object.values(AUTO_BLOCKS)) {
    const b = blocks.find(x => x.type === type);
    if (b) return b;
  }
  return { label: type, color: "#555", dot: "#555" };
}

// ── couleur du fil selon le type de port ──────────────────────
const WIRE_COLORS = { default: "#4a5568", true: "#00e08a", false: "#e74c3c", data: "#7c5cff" };

// ── ports par type ────────────────────────────────────────────
function getPorts(type) {
  const isTrigger = type.startsWith("trigger_");
  const isCondition = type === "logic_condition";
  const isMerge = type === "logic_merge";
  const isSplit = type === "logic_split";
  const inputs = isTrigger ? [] : ["in"];
  const outputs = isCondition ? ["true", "false"] : isSplit ? ["out1","out2","out3"] : isMerge ? ["out"] : ["out"];
  const inputDefs = isMerge ? [{ id: "in1", label: "" }, { id: "in2", label: "" }, { id: "in3", label: "" }]
    : inputs.map(id => ({ id, label: "" }));
  const outputDefs = outputs.map(id => ({ id, label: isCondition ? id : "" }));
  return { inputs: inputDefs, outputs: outputDefs };
}

// NODE_WIDTH
const NW = 190;

// ── store automations ─────────────────────────────────────────
const AutoStore = (function () {
  const KEY = "nkreal.automations.v2";
  let data = [];
  try { data = JSON.parse(localStorage.getItem(KEY) || "[]"); } catch (e) {}
  const ls = new Set();
  const save = () => { try { localStorage.setItem(KEY, JSON.stringify(data)); } catch (e) {} ls.forEach(f => f()); };
  return {
    sub(cb) { ls.add(cb); return () => ls.delete(cb); },
    list() { return data; },
    add(a) { data = [a, ...data]; save(); },
    update(id, patch) { data = data.map(a => a.id === id ? { ...a, ...patch } : a); save(); },
    del(id) { data = data.filter(a => a.id !== id); save(); },
  };
})();
function useAutoStore() {
  const [, f] = React.useReducer(x => x + 1, 0);
  React.useEffect(() => AutoStore.sub(f), []);
  return AutoStore;
}

// ── Palette gauche ────────────────────────────────────────────
function Palette() {
  const [open, setOpen] = React.useState(
    Object.keys(AUTO_BLOCKS).reduce((a, k) => ({ ...a, [k]: true }), {})
  );
  return (
    <div style={{ width: 210, flex: "none", background: "#0f1117", borderRight: "1px solid #1e2130", overflowY: "auto", display: "flex", flexDirection: "column", userSelect: "none" }}>
      {Object.entries(AUTO_BLOCKS).map(([cat, blocks]) => (
        <div key={cat}>
          <div onClick={() => setOpen(o => ({ ...o, [cat]: !o[cat] }))} style={{ padding: "7px 14px 5px", display: "flex", alignItems: "center", gap: 6, cursor: "pointer", color: "#6b7280" }}>
            <span style={{ fontSize: 9, fontWeight: 700, letterSpacing: ".1em", textTransform: "uppercase", flex: 1 }}>{cat}</span>
            <span style={{ fontSize: 10, opacity: .5 }}>{open[cat] ? "▾" : "▸"}</span>
          </div>
          {open[cat] && blocks.map(b => (
            <div key={b.type} draggable
              onDragStart={e => e.dataTransfer.setData("blockType", b.type)}
              style={{ margin: "1px 8px", padding: "5px 9px", borderRadius: 5, background: "#141720", border: "1px solid #1e2130", cursor: "grab", display: "flex", alignItems: "center", gap: 8 }}
              onMouseEnter={e => e.currentTarget.style.background = "#1a1f2e"}
              onMouseLeave={e => e.currentTarget.style.background = "#141720"}
            >
              <span style={{ width: 8, height: 8, borderRadius: "50%", background: b.dot, flex: "none" }} />
              <span style={{ fontSize: 11.5, color: "#cbd5e1", flex: 1, lineHeight: 1.3 }}>{b.label}</span>
            </div>
          ))}
        </div>
      ))}
    </div>
  );
}

// ── Nœud sur le canvas ────────────────────────────────────────
function NodeCard({ node, selected, onSelect, onDragStart, portRefs, onPortMouseDown, onPortMouseUp }) {
  const def = blockDef(node.type);
  const { inputs, outputs } = getPorts(node.type);
  const fields = BLOCK_FIELDS[node.type] || [];

  return (
    <div
      onMouseDown={e => { e.stopPropagation(); onSelect(node.id); onDragStart(e, node.id); }}
      style={{
        position: "absolute", left: node.x, top: node.y, width: NW,
        background: "#141720", border: `1.5px solid ${selected ? def.color : "#1e2534"}`,
        borderRadius: 8, boxShadow: selected ? `0 0 0 2px ${def.color}44` : "0 4px 20px rgba(0,0,0,.5)",
        cursor: "grab", zIndex: selected ? 10 : 1, userSelect: "none",
      }}
    >
      {/* header */}
      <div style={{ padding: "7px 10px 6px", borderBottom: "1px solid #1e2534", display: "flex", alignItems: "center", gap: 7, borderRadius: "6px 6px 0 0", background: def.color + "18" }}>
        <span style={{ width: 8, height: 8, borderRadius: "50%", background: def.color, flex: "none" }} />
        <span style={{ fontSize: 12, fontWeight: 700, color: "#e2e8f0", flex: 1, lineHeight: 1.2 }}>{def.label}</span>
      </div>
      {/* ports + fields */}
      <div style={{ position: "relative", minHeight: Math.max(inputs.length, outputs.length) * 24 + (fields.length ? fields.length * 38 + 8 : 0) }}>
        {/* INPUT ports */}
        {inputs.map((p, i) => (
          <div key={p.id} ref={el => { if (portRefs) portRefs.current[`${node.id}:in:${p.id}`] = el; }}
            onMouseUp={e => { e.stopPropagation(); onPortMouseUp && onPortMouseUp(node.id, "in", p.id, e); }}
            style={{ position: "absolute", left: -7, top: 10 + i * 24, width: 14, height: 14, borderRadius: "50%", background: "#1e2534", border: "2px solid #6b7280", cursor: "crosshair", zIndex: 20 }}
            onMouseEnter={e => e.currentTarget.style.borderColor = def.color}
            onMouseLeave={e => e.currentTarget.style.borderColor = "#6b7280"}
          />
        ))}
        {/* OUTPUT ports */}
        {outputs.map((p, i) => (
          <div key={p.id} ref={el => { if (portRefs) portRefs.current[`${node.id}:out:${p.id}`] = el; }}
            onMouseDown={e => { e.stopPropagation(); onPortMouseDown && onPortMouseDown(node.id, "out", p.id, e); }}
            style={{ position: "absolute", right: -7, top: 10 + i * 24, width: 14, height: 14, borderRadius: "50%", background: "#1e2534", border: `2px solid ${p.id === "true" ? "#00e08a" : p.id === "false" ? "#e74c3c" : "#6b7280"}`, cursor: "crosshair", zIndex: 20, display: "flex", alignItems: "center" }}
            onMouseEnter={e => e.currentTarget.style.borderColor = def.color}
            onMouseLeave={e => e.currentTarget.style.borderColor = p.id === "true" ? "#00e08a" : p.id === "false" ? "#e74c3c" : "#6b7280"}
          >
            {p.label && <span style={{ position: "absolute", right: 18, fontSize: 9, color: p.id === "true" ? "#00e08a" : "#e74c3c", whiteSpace: "nowrap", fontWeight: 700, textTransform: "uppercase" }}>{p.label}</span>}
          </div>
        ))}
        {/* fields */}
        {fields.length > 0 && selected && (
          <div style={{ padding: "8px 10px 6px", display: "grid", gap: 5 }} onMouseDown={e => e.stopPropagation()}>
            {fields.map(f => (
              <label key={f.key} style={{ display: "flex", flexDirection: "column", gap: 3 }}>
                <span style={{ fontSize: 9, fontWeight: 700, letterSpacing: ".08em", textTransform: "uppercase", color: "#6b7280" }}>{f.label}</span>
                {f.type === "select" ? (
                  <select defaultValue={node.config?.[f.key] || ""}
                    onChange={e => { node.config = { ...node.config, [f.key]: e.target.value }; }}
                    style={{ padding: "4px 7px", background: "#0f1117", border: "1px solid #1e2534", borderRadius: 5, color: "#cbd5e1", fontSize: 11, outline: "none" }}>
                    {f.opts.map(o => <option key={o} value={o}>{o}</option>)}
                  </select>
                ) : (
                  <input defaultValue={node.config?.[f.key] || ""} placeholder={f.ph}
                    onChange={e => { node.config = { ...node.config, [f.key]: e.target.value }; }}
                    style={{ padding: "4px 7px", background: "#0f1117", border: "1px solid #1e2534", borderRadius: 5, color: "#cbd5e1", fontSize: 11, outline: "none" }} />
                )}
              </label>
            ))}
          </div>
        )}
        {/* résumé config (non sélectionné) */}
        {fields.length > 0 && !selected && node.config && Object.values(node.config).filter(Boolean).length > 0 && (
          <div style={{ padding: "5px 10px 6px" }}>
            {Object.entries(node.config).filter(([, v]) => v).slice(0, 2).map(([k, v]) => (
              <div key={k} style={{ fontSize: 10, color: "#6b7280", overflow: "hidden", textOverflow: "ellipsis", whiteSpace: "nowrap" }}>
                <span style={{ color: "#4b5563" }}>{k}: </span><span style={{ color: "#94a3b8" }}>{v}</span>
              </div>
            ))}
          </div>
        )}
      </div>
    </div>
  );
}

// ── Calcule la position d'un port dans le canvas ──────────────
function getPortCenter(portRefs, key, canvasRef) {
  const el = portRefs.current[key];
  if (!el || !canvasRef.current) return null;
  const eRect = el.getBoundingClientRect();
  const cRect = canvasRef.current.getBoundingClientRect();
  return {
    x: eRect.left + eRect.width / 2 - cRect.left,
    y: eRect.top + eRect.height / 2 - cRect.top,
  };
}

// ── Bezier entre deux points ──────────────────────────────────
function bezier(x1, y1, x2, y2) {
  const dx = Math.abs(x2 - x1) * 0.6;
  return `M${x1},${y1} C${x1 + dx},${y1} ${x2 - dx},${y2} ${x2},${y2}`;
}

// ── Canvas éditeur principal ──────────────────────────────────
function NodeCanvas({ graph, setGraph }) {
  const canvasRef = React.useRef(null);
  const portRefs = React.useRef({});
  const [selected, setSelected] = React.useState(null);
  // pan
  const [pan, setPan] = React.useState({ x: 0, y: 0 });
  const [zoom, setZoom] = React.useState(1);
  const panRef = React.useRef(null);
  // drag node
  const dragRef = React.useRef(null);
  // drawing wire
  const [wire, setWire] = React.useState(null); // { fromNode, fromPort, mx, my }
  const [, forceUpdate] = React.useReducer(x => x + 1, 0);

  // canvas → world coords
  const toWorld = (cx, cy) => ({ x: (cx - pan.x) / zoom, y: (cy - pan.y) / zoom });

  // ── drop bloc depuis palette
  const handleDrop = (e) => {
    e.preventDefault();
    const type = e.dataTransfer.getData("blockType");
    if (!type) return;
    const rect = canvasRef.current.getBoundingClientRect();
    const { x, y } = toWorld(e.clientX - rect.left, e.clientY - rect.top);
    const id = "n" + Date.now();
    setGraph(g => ({ ...g, nodes: [...g.nodes, { id, type, x: x - NW / 2, y: y - 20, config: {} }] }));
  };

  // ── drag nœud
  const onNodeDragStart = (e, nodeId) => {
    const node = graph.nodes.find(n => n.id === nodeId);
    dragRef.current = { nodeId, startMX: e.clientX, startMY: e.clientY, origX: node.x, origY: node.y };
  };

  // ── pan du canvas (clic fond)
  const onCanvasMouseDown = (e) => {
    if (e.target === canvasRef.current || e.target.tagName === "svg" || e.target.tagName === "path") {
      setSelected(null);
      panRef.current = { startMX: e.clientX, startMY: e.clientY, origPan: { ...pan } };
    }
  };

  const onMouseMove = (e) => {
    if (dragRef.current) {
      const dx = (e.clientX - dragRef.current.startMX) / zoom;
      const dy = (e.clientY - dragRef.current.startMY) / zoom;
      setGraph(g => ({
        ...g,
        nodes: g.nodes.map(n => n.id === dragRef.current.nodeId ? { ...n, x: dragRef.current.origX + dx, y: dragRef.current.origY + dy } : n),
      }));
    }
    if (panRef.current) {
      const dx = e.clientX - panRef.current.startMX;
      const dy = e.clientY - panRef.current.startMY;
      setPan({ x: panRef.current.origPan.x + dx, y: panRef.current.origPan.y + dy });
    }
    if (wire) {
      const rect = canvasRef.current.getBoundingClientRect();
      setWire(w => ({ ...w, mx: e.clientX - rect.left, my: e.clientY - rect.top }));
    }
  };

  const onMouseUp = (e) => {
    dragRef.current = null;
    panRef.current = null;
    if (wire && !wire.connected) setWire(null);
  };

  // ── port interactions
  const onPortMouseDown = (nodeId, dir, portId, e) => {
    e.stopPropagation();
    const rect = canvasRef.current.getBoundingClientRect();
    setWire({ fromNode: nodeId, fromPort: portId, mx: e.clientX - rect.left, my: e.clientY - rect.top, connected: false });
  };

  const onPortMouseUp = (nodeId, dir, portId, e) => {
    if (!wire || wire.fromNode === nodeId) { setWire(null); return; }
    // évite les doublons
    const exists = graph.edges.some(ed => ed.from === wire.fromNode && ed.fromPort === wire.fromPort && ed.to === nodeId && ed.toPort === portId);
    if (!exists) {
      setGraph(g => ({ ...g, edges: [...g.edges, { id: `e${Date.now()}`, from: wire.fromNode, fromPort: wire.fromPort, to: nodeId, toPort: portId }] }));
    }
    setWire(null);
    forceUpdate();
  };

  // ── zoom molette
  const onWheel = (e) => {
    e.preventDefault();
    const factor = e.deltaY < 0 ? 1.1 : 0.9;
    setZoom(z => Math.min(2.5, Math.max(0.2, z * factor)));
  };

  // ── supprime nœud ou edge sélectionné
  const onKeyDown = (e) => {
    if ((e.key === "Delete" || e.key === "Backspace") && selected && e.target.tagName !== "INPUT" && e.target.tagName !== "SELECT") {
      setGraph(g => ({
        nodes: g.nodes.filter(n => n.id !== selected),
        edges: g.edges.filter(ed => ed.from !== selected && ed.to !== selected),
      }));
      setSelected(null);
    }
  };

  React.useEffect(() => {
    window.addEventListener("keydown", onKeyDown);
    return () => window.removeEventListener("keydown", onKeyDown);
  }, [selected, graph]);

  // ── rendu des fils
  const [, tick] = React.useReducer(x => x + 1, 0);
  React.useEffect(() => { tick(); }, [graph.nodes, graph.edges]);

  const wireColor = (portId) => portId === "true" ? "#00e08a" : portId === "false" ? "#e74c3c" : portId === "out1" || portId === "out2" || portId === "out3" ? "#7c5cff" : "#3b82f6";

  return (
    <div ref={canvasRef} tabIndex={0}
      style={{ flex: 1, overflow: "hidden", position: "relative", background: "#0b0d13", cursor: "default", outline: "none" }}
      onMouseDown={onCanvasMouseDown} onMouseMove={onMouseMove} onMouseUp={onMouseUp}
      onDragOver={e => e.preventDefault()} onDrop={handleDrop}
      onWheel={onWheel}
    >
      {/* grille de points */}
      <svg style={{ position: "absolute", inset: 0, width: "100%", height: "100%", pointerEvents: "none" }}>
        <defs>
          <pattern id="grid" x={pan.x % (20 * zoom)} y={pan.y % (20 * zoom)} width={20 * zoom} height={20 * zoom} patternUnits="userSpaceOnUse">
            <circle cx={1} cy={1} r={.7} fill="#1e2534" />
          </pattern>
        </defs>
        <rect width="100%" height="100%" fill="url(#grid)" />
      </svg>

      {/* conteneur transformé */}
      <div style={{ position: "absolute", inset: 0, transform: `translate(${pan.x}px,${pan.y}px) scale(${zoom})`, transformOrigin: "0 0" }}>
        {/* SVG fils */}
        <svg style={{ position: "absolute", inset: 0, width: "200%", height: "200%", overflow: "visible", pointerEvents: "none" }}>
          {graph.edges.map(ed => {
            const fromKey = `${ed.from}:out:${ed.fromPort}`;
            const toKey = `${ed.to}:in:${ed.toPort}`;
            const fp = getPortCenter(portRefs, fromKey, canvasRef);
            const tp = getPortCenter(portRefs, toKey, canvasRef);
            if (!fp || !tp) return null;
            // convertir en coordonnées world
            const fx = (fp.x - pan.x) / zoom, fy = (fp.y - pan.y) / zoom;
            const tx = (tp.x - pan.x) / zoom, ty = (tp.y - pan.y) / zoom;
            const c = wireColor(ed.fromPort);
            return (
              <path key={ed.id} d={bezier(fx, fy, tx, ty)} fill="none" stroke={c} strokeWidth={1.8} strokeOpacity={.85}
                style={{ pointerEvents: "auto", cursor: "pointer" }}
                onClick={() => setGraph(g => ({ ...g, edges: g.edges.filter(x => x.id !== ed.id) }))}
              />
            );
          })}
          {/* fil en cours */}
          {wire && (() => {
            const fromKey = `${wire.fromNode}:out:${wire.fromPort}`;
            const fp = getPortCenter(portRefs, fromKey, canvasRef);
            if (!fp) return null;
            const fx = (fp.x - pan.x) / zoom, fy = (fp.y - pan.y) / zoom;
            const tx = (wire.mx - pan.x) / zoom, ty = (wire.my - pan.y) / zoom;
            return <path d={bezier(fx, fy, tx, ty)} fill="none" stroke="#4b5563" strokeWidth={1.5} strokeDasharray="5 3" />;
          })()}
        </svg>

        {/* nœuds */}
        {graph.nodes.map(node => (
          <NodeCard key={node.id} node={node} selected={selected === node.id}
            onSelect={setSelected} onDragStart={onNodeDragStart}
            portRefs={portRefs} onPortMouseDown={onPortMouseDown} onPortMouseUp={onPortMouseUp} />
        ))}
      </div>

      {/* hint bas */}
      {graph.nodes.length === 0 && (
        <div style={{ position: "absolute", inset: 0, display: "flex", flexDirection: "column", alignItems: "center", justifyContent: "center", pointerEvents: "none", color: "#374151" }}>
          <div style={{ fontSize: 40, marginBottom: 12 }}>⚡</div>
          <div style={{ fontSize: 14, marginBottom: 6 }}>Glisse des blocs depuis la palette</div>
          <div style={{ fontSize: 12 }}>Connecte les ports pour créer ta séquence</div>
        </div>
      )}

      {/* zoom indicator */}
      <div style={{ position: "absolute", bottom: 14, right: 14, display: "flex", gap: 6, alignItems: "center" }}>
        <button onClick={() => setZoom(z => Math.min(2.5, z * 1.2))} style={{ width: 28, height: 28, borderRadius: 6, background: "#141720", border: "1px solid #1e2534", color: "#94a3b8", cursor: "pointer", fontSize: 16, display: "grid", placeItems: "center" }}>+</button>
        <span style={{ fontSize: 11, color: "#4b5563", minWidth: 36, textAlign: "center" }}>{Math.round(zoom * 100)}%</span>
        <button onClick={() => setZoom(z => Math.max(0.2, z * 0.8))} style={{ width: 28, height: 28, borderRadius: 6, background: "#141720", border: "1px solid #1e2534", color: "#94a3b8", cursor: "pointer", fontSize: 16, display: "grid", placeItems: "center" }}>−</button>
        <button onClick={() => { setPan({ x: 0, y: 0 }); setZoom(1); }} style={{ padding: "0 10px", height: 28, borderRadius: 6, background: "#141720", border: "1px solid #1e2534", color: "#6b7280", cursor: "pointer", fontSize: 11 }}>Reset</button>
      </div>

      {/* hint delete */}
      {selected && (
        <div style={{ position: "absolute", bottom: 14, left: "50%", transform: "translateX(-50%)", background: "#141720", border: "1px solid #1e2534", borderRadius: 6, padding: "5px 12px", fontSize: 11, color: "#6b7280", pointerEvents: "none" }}>
          Suppr / Backspace pour supprimer · Clic sur un fil pour le couper
        </div>
      )}
    </div>
  );
}

// ── Éditeur complet (barre + canvas) ─────────────────────────
function AutoEditor({ auto, onSave, onCancel }) {
  const [name, setName] = React.useState(auto?.name || "Nouvelle automation");
  const [graph, setGraph] = React.useState(auto?.graph || { nodes: [], edges: [] });

  const save = () => {
    onSave({ id: auto?.id || String(Date.now()), name, graph, enabled: auto?.enabled ?? true, created: auto?.created || new Date().toISOString() });
  };

  return (
    <div style={{ display: "flex", flexDirection: "column", height: "100%", background: "#0b0d13" }}>
      {/* barre supérieure */}
      <div style={{ display: "flex", alignItems: "center", gap: 10, padding: "10px 16px", borderBottom: "1px solid #1e2534", background: "#0f1117", flex: "none" }}>
        <button onClick={onCancel} style={{ background: "#141720", border: "1px solid #1e2534", borderRadius: 7, padding: "6px 12px", color: "#94a3b8", fontSize: 12, cursor: "pointer" }}>← Retour</button>
        <input value={name} onChange={e => setName(e.target.value)}
          style={{ flex: "none", width: 260, padding: "6px 12px", background: "#141720", border: "1px solid #1e2534", borderRadius: 7, color: "#e2e8f0", fontSize: 14, fontWeight: 600, outline: "none" }} />
        <span style={{ fontSize: 11, color: "#374151" }}>{graph.nodes.length} nœuds · {graph.edges.length} connexions</span>
        <div style={{ flex: 1 }} />
        <button onClick={() => setGraph({ nodes: [], edges: [] })} style={{ background: "#141720", border: "1px solid #374151", borderRadius: 7, padding: "6px 12px", color: "#6b7280", fontSize: 12, cursor: "pointer" }}>Vider</button>
        <button onClick={save} disabled={!name.trim()} style={{ background: "var(--accent,#fff)", border: "none", borderRadius: 7, padding: "7px 18px", color: "#000", fontSize: 13, fontWeight: 700, cursor: "pointer" }}>Sauvegarder</button>
      </div>
      {/* palette + canvas */}
      <div style={{ display: "flex", flex: 1, overflow: "hidden" }}>
        <Palette />
        <NodeCanvas graph={graph} setGraph={setGraph} />
      </div>
    </div>
  );
}

// ── Liste des automations ─────────────────────────────────────
function AutoList({ onNew, onEdit }) {
  const store = useAutoStore();
  const autos = store.list();

  return (
    <div style={{ padding: "28px 32px", maxWidth: 860, margin: "0 auto", width: "100%" }}>
      <div style={{ display: "flex", justifyContent: "space-between", alignItems: "flex-end", marginBottom: 22, gap: 14, flexWrap: "wrap" }}>
        <SectionTitle sub="Séquences d'actions automatiques sur les iPhones">Automations</SectionTitle>
        <button onClick={onNew} style={{ background: "var(--accent,#fff)", border: "none", borderRadius: 9, padding: "9px 18px", color: "#000", fontSize: 13, fontWeight: 700, cursor: "pointer" }}>
          + Nouvelle automation
        </button>
      </div>
      {autos.length === 0 ? (
        <div style={{ textAlign: "center", padding: "70px 20px", color: "var(--faint,#555)" }}>
          <div style={{ fontSize: 52, marginBottom: 14, opacity: .2 }}>⚡</div>
          <div style={{ fontSize: 15, marginBottom: 8 }}>Aucune automation</div>
          <div style={{ fontSize: 13 }}>Crée ta première automation pour piloter tes iPhones automatiquement</div>
        </div>
      ) : (
        <div style={{ display: "flex", flexDirection: "column", gap: 10 }}>
          {autos.map(a => {
            const nodeCount = (a.graph?.nodes || []).length;
            const edgeCount = (a.graph?.edges || []).length;
            const trigger = (a.graph?.nodes || []).find(n => n.type.startsWith("trigger_"));
            const trigDef = trigger ? blockDef(trigger.type) : null;
            return (
              <div key={a.id} onClick={() => onEdit(a)}
                style={{ padding: "14px 18px", background: "var(--surface,#111)", border: "1px solid var(--border,#222)", borderRadius: 12, display: "flex", alignItems: "center", gap: 14, cursor: "pointer", transition: "border-color .15s" }}
                onMouseEnter={e => e.currentTarget.style.borderColor = "var(--border-2,#333)"}
                onMouseLeave={e => e.currentTarget.style.borderColor = "var(--border,#222)"}
              >
                {/* toggle */}
                <div onClick={e => { e.stopPropagation(); store.update(a.id, { enabled: !a.enabled }); }}
                  style={{ width: 36, height: 20, borderRadius: 10, background: a.enabled ? "#00e08a" : "var(--surface-3,#1a1a1a)", border: "1px solid " + (a.enabled ? "#00e08a" : "var(--border,#222)"), cursor: "pointer", display: "flex", alignItems: "center", padding: "0 3px", flex: "none", transition: "background .2s" }}>
                  <div style={{ width: 14, height: 14, borderRadius: "50%", background: "#fff", transform: a.enabled ? "translateX(16px)" : "none", transition: "transform .2s", boxShadow: "0 1px 3px rgba(0,0,0,.3)" }} />
                </div>
                <div style={{ flex: 1, minWidth: 0 }}>
                  <div style={{ fontSize: 14, fontWeight: 600, color: "var(--text,#eee)", marginBottom: 4 }}>{a.name}</div>
                  <div style={{ display: "flex", gap: 8, flexWrap: "wrap", alignItems: "center" }}>
                    {trigDef && <span style={{ fontSize: 11, color: "#22d3ee", background: "#22d3ee15", padding: "2px 8px", borderRadius: 5, border: "1px solid #22d3ee30" }}>{trigDef.label}</span>}
                    <span style={{ fontSize: 11, color: "var(--faint,#555)" }}>{nodeCount} nœud{nodeCount !== 1 ? "s" : ""} · {edgeCount} connexion{edgeCount !== 1 ? "s" : ""}</span>
                  </div>
                </div>
                <div style={{ display: "flex", gap: 8, flex: "none" }} onClick={e => e.stopPropagation()}>
                  <button onClick={() => onEdit(a)} style={{ background: "var(--surface-2,#1a1a1a)", border: "1px solid var(--border,#222)", borderRadius: 7, padding: "6px 12px", color: "var(--text,#eee)", fontSize: 12, cursor: "pointer" }}>✏️ Éditer</button>
                  <button onClick={() => { if (confirm("Supprimer cette automation ?")) store.del(a.id); }}
                    style={{ background: "#e74c3c15", border: "1px solid #e74c3c30", borderRadius: 7, padding: "6px 12px", color: "#e74c3c", fontSize: 12, cursor: "pointer" }}>Suppr.</button>
                </div>
              </div>
            );
          })}
        </div>
      )}
    </div>
  );
}

// ── Composant principal exporté ───────────────────────────────
function AdminAutomation() {
  const store = useAutoStore();
  const [view, setView] = React.useState("list");
  const [editing, setEditing] = React.useState(null);

  if (view === "editor") {
    return (
      <div style={{ display: "flex", flexDirection: "column", height: "calc(100vh - 0px)", overflow: "hidden" }}>
        <AutoEditor auto={editing}
          onSave={a => { editing ? store.update(a.id, a) : store.add(a); setView("list"); }}
          onCancel={() => setView("list")} />
      </div>
    );
  }

  return (
    <div style={{ overflowY: "auto", flex: 1 }}>
      <AutoList onNew={() => { setEditing(null); setView("editor"); }} onEdit={a => { setEditing(a); setView("editor"); }} />
    </div>
  );
}
