<template>
  <!-- Éditeur de flows VISUEL node-based (Vue Flow, port Vue de React Flow — esthétique n8n). Lit/édite le MÊME modèle de steps (id/parent/branch/type). -->
  <div class="flow-canvas">
    <div v-if="editable" class="fc-toolbar">
      <q-btn dense unelevated no-caps color="primary" icon="add" label="Ajouter une étape" size="sm" @click="emit('add')" />
      <span class="fc-hint">Tirez d'un point à l'autre pour relier · clic = éditer · ✕ = supprimer · glissez pour ranger</span>
    </div>
    <VueFlow :nodes="nodes" :edges="edges" :min-zoom="0.2" :max-zoom="2" fit-view-on-init
      :default-edge-options="{ type: 'smoothstep' }" :nodes-connectable="editable" :nodes-draggable="true"
      @connect="onConnect" @node-click="onNodeClick" @node-drag-stop="onDragStop">
      <Background pattern-color="#d6deea" :gap="18" />
      <Controls />
      <template #node-flowstep="{ id, data }">
        <Handle type="target" :position="Position.Left" />
        <div class="fc-node" :style="{ borderColor: data.color }">
          <button v-if="editable" class="fc-del" title="Supprimer" @click.stop="emit('delete', id)">✕</button>
          <div class="fc-node-type" :style="{ color: data.color }">{{ data.icon }} {{ data.typeLabel }}</div>
          <div class="fc-node-label">{{ data.label }}</div>
        </div>
        <Handle type="source" :position="Position.Right" />
      </template>
    </VueFlow>
    <div v-if="!nodes.length" class="fc-empty">Aucune étape — « Ajouter une étape » pour commencer.</div>
  </div>
</template>

<script setup>
import { ref, watch } from 'vue'
import { VueFlow, Handle, Position } from '@vue-flow/core'
import { Background } from '@vue-flow/background'
import { Controls } from '@vue-flow/controls'
import '@vue-flow/core/dist/style.css'
import '@vue-flow/core/dist/theme-default.css'
import '@vue-flow/controls/dist/style.css'

const props = defineProps({ steps: { type: Array, default: () => [] }, editable: { type: Boolean, default: true } })
const emit = defineEmits(['edit', 'delete', 'add', 'connect', 'move'])

const TYPE_META = {
  tool: { c: '#0ea5e9', i: '🔧', l: 'Outil' }, condition: { c: '#f59e0b', i: '❓', l: 'Condition' },
  switch: { c: '#f59e0b', i: '🔀', l: 'Switch' }, respond: { c: '#10b981', i: '💬', l: 'Réponse' },
  action: { c: '#6366f1', i: '⚙️', l: 'Action' }, goto: { c: '#64748b', i: '↪️', l: 'Aller à' },
}

const nodes = ref([])
const edges = ref([])

// Layout : position manuelle (step._pos, persistée) sinon arbre auto (profondeur→X, ordre→Y).
function rebuild () {
  const steps = props.steps || []
  const byId = {}; for (const s of steps) byId[s.id] = s
  const depthOf = (s) => { let d = 0, cur = s; const seen = new Set(); while (cur && cur.parent != null && byId[cur.parent] && !seen.has(cur.id)) { seen.add(cur.id); cur = byId[cur.parent]; d++ } return d }
  const perDepth = {}; const n = []
  for (const s of steps) {
    const d = depthOf(s); perDepth[d] = perDepth[d] || 0
    const m = TYPE_META[s.type] || TYPE_META.action
    const pos = (s._pos && typeof s._pos.x === 'number') ? { x: s._pos.x, y: s._pos.y } : { x: d * 300, y: perDepth[d] * 130 }
    n.push({ id: String(s.id), type: 'flowstep', position: pos, data: { label: s.label || s.id, typeLabel: m.l, icon: m.i, color: m.c } })
    perDepth[d]++
  }
  const e = []
  for (const s of steps) { if (s.parent != null && byId[s.parent]) e.push({ id: `e-${s.parent}-${s.id}`, source: String(s.parent), target: String(s.id), label: s.branch || '', labelBgPadding: [4, 2], style: { stroke: '#94a3b8' }, labelStyle: { fontSize: '11px', fill: '#64748b' } }) }
  nodes.value = n; edges.value = e
}
watch(() => props.steps, rebuild, { immediate: true, deep: true })

function onNodeClick (e) { if (e && e.node) emit('edit', e.node.id) }
function onConnect (params) { if (params && params.source && params.target) emit('connect', { source: params.source, target: params.target }) }
function onDragStop (e) { const node = (e && e.node) || (e && e.nodes && e.nodes[0]); if (node) emit('move', { id: node.id, position: { x: node.position.x, y: node.position.y } }) }
</script>

<style scoped>
.flow-canvas { position: relative; height: 580px; border: 1px solid #e2e8f0; border-radius: 10px; background: #fafbfc; overflow: hidden; }
.fc-toolbar { position: absolute; top: 8px; left: 8px; z-index: 5; display: flex; align-items: center; gap: 10px; }
.fc-hint { font-size: 11px; color: #94a3b8; background: rgba(255,255,255,.7); padding: 2px 6px; border-radius: 6px; }
.fc-node { position: relative; background: #fff; border: 2px solid #6366f1; border-radius: 10px; padding: 8px 12px; min-width: 160px; max-width: 230px; box-shadow: 0 1px 5px rgba(15,23,42,.08); }
.fc-node-type { font-size: 10px; font-weight: 700; text-transform: uppercase; letter-spacing: .04em; margin-bottom: 2px; }
.fc-node-label { font-size: 13px; color: #1e293b; line-height: 1.25; }
.fc-del { position: absolute; top: -8px; right: -8px; width: 18px; height: 18px; border-radius: 50%; border: none; background: #ef4444; color: #fff; font-size: 11px; line-height: 1; cursor: pointer; display: none; }
.fc-node:hover .fc-del { display: block; }
.fc-empty { position: absolute; inset: 0; display: flex; align-items: center; justify-content: center; color: #94a3b8; font-size: 0.9rem; pointer-events: none; }
</style>
