<template>
  <div class="h-full w-full vue-flow-monokai" ref="canvasWrapper">
    <VueFlow
      v-model:nodes="archStore.nodes"
      v-model:edges="archStore.edges"
      :node-types="nodeTypes"
      :connection-mode="ConnectionMode.Loose"
      :snap-to-grid="true"
      :snap-grid="[10, 10]"
      :default-edge-options="defaultEdgeOptions"
      :fit-view-on-init="true"
      :delete-key-code="['Delete', 'Backspace']"
      @node-click="onNodeClick"
      @edge-click="onEdgeClick"
      @pane-click="onPaneClick"
      @connect="onConnect"
      @nodes-delete="onNodesDelete"
      @edges-delete="onEdgesDelete"
      @node-drag-stop="onNodeDragStop"
      @drop="onDrop"
      @dragover.prevent="onDragOver"
    >
      <Background :color="'#75715E'" :gap="20" pattern-color="#75715E33" />
      <Controls position="top-right" />
      <MiniMap
        :node-color="miniMapNodeColor"
        :mask-color="'rgba(39, 40, 34, 0.8)'"
        position="bottom-right"
      />
    </VueFlow>
  </div>
</template>

<script setup>
import { ref, markRaw } from 'vue'
import { VueFlow, useVueFlow, ConnectionMode } from '@vue-flow/core'
import { Background } from '@vue-flow/background'
import { Controls } from '@vue-flow/controls'
import { MiniMap } from '@vue-flow/minimap'
import '@vue-flow/core/dist/style.css'
import '@vue-flow/core/dist/theme-default.css'
import '@vue-flow/controls/dist/style.css'
import '@vue-flow/minimap/dist/style.css'
import '@vue-flow/node-resizer/dist/style.css'

import ArchNode from './nodes/ArchNode.vue'
import { useArchitectureStore } from '@/stores/architectureStore'

const archStore = useArchitectureStore()
const canvasWrapper = ref(null)

const { project } = useVueFlow()

// Enregistrer le type de noeud custom
const nodeTypes = {
  'arch-node': markRaw(ArchNode),
}

// Options par défaut des edges (courbes bézier)
const defaultEdgeOptions = {
  type: 'default',
  animated: false,
  style: { stroke: '#56A7FF', strokeWidth: 2 },
}

// --- Événements ---

function onNodeClick({ node }) {
  archStore.selectNode(node.id)
}

function onEdgeClick({ edge }) {
  archStore.selectEdge(edge.id)
}

function onPaneClick() {
  archStore.clearSelection()
}

function onConnect(connection) {
  archStore.addEdge(connection)
}

function onNodesDelete(deletedNodes) {
  for (const node of deletedNodes) {
    if (node.data?.locked) continue
    archStore.removeNode(node.id)
  }
}

function onEdgesDelete(deletedEdges) {
  for (const edge of deletedEdges) {
    archStore.removeEdge(edge.id)
  }
}

function onNodeDragStop({ node }) {
  // Mettre à jour la position dans le store
  const idx = archStore.nodes.findIndex(n => n.id === node.id)
  if (idx !== -1) {
    archStore.nodes[idx] = {
      ...archStore.nodes[idx],
      position: { ...node.position }
    }
  }
}

// --- Drag & Drop depuis la palette ---

function onDragOver(event) {
  event.dataTransfer.dropEffect = 'move'
}

/**
 * Calcule la position absolue d'un noeud (en remontant la chaîne parentNode)
 */
function getAbsolutePosition(nodeId) {
  const node = archStore.nodes.find(n => n.id === nodeId)
  if (!node) return { x: 0, y: 0 }
  let x = node.position.x
  let y = node.position.y
  if (node.parentNode) {
    const parentPos = getAbsolutePosition(node.parentNode)
    x += parentPos.x
    y += parentPos.y
  }
  return { x, y }
}

/**
 * Trouve le noeud parent le plus spécifique (le plus petit) contenant la position absolue
 */
function findParentAtPosition(absPos) {
  let bestParent = null
  let bestArea = Infinity

  for (const node of archStore.nodes) {
    const nodeAbsPos = getAbsolutePosition(node.id)
    const w = parseFloat(node.style?.width) || 120
    const h = parseFloat(node.style?.height) || 44

    if (absPos.x >= nodeAbsPos.x && absPos.x <= nodeAbsPos.x + w &&
        absPos.y >= nodeAbsPos.y && absPos.y <= nodeAbsPos.y + h) {
      const area = w * h
      if (area < bestArea) {
        bestArea = area
        bestParent = node
      }
    }
  }
  return bestParent
}

function onDrop(event) {
  const toolId = event.dataTransfer.getData('application/archnode')
  if (!toolId) return

  // Convertir la position écran en position du flow (absolue)
  const absPosition = project({
    x: event.clientX,
    y: event.clientY,
  })

  // Détecter si on drop sur un noeud existant → nesting
  const parent = findParentAtPosition(absPosition)

  if (parent) {
    // Position relative au parent
    const parentAbsPos = getAbsolutePosition(parent.id)
    const relativePosition = {
      x: absPosition.x - parentAbsPos.x,
      y: absPosition.y - parentAbsPos.y,
    }
    archStore.addNode(toolId, relativePosition, parent.id)
  } else {
    archStore.addNode(toolId, absPosition)
  }
}

// --- MiniMap ---

function miniMapNodeColor(node) {
  if (node.data?.online) return '#A6E22E'
  const colors = {
    world: '#E6E6E6',
    home: '#8F6FE3',
    computer: '#B5B5B5',
    network: '#56A7FF',
    room: '#C8A08A',
    vm: '#62D36E',
    service: '#F0A33A',
  }
  return colors[node.data?.nodeType] || '#75715E'
}
</script>

<style>
/* Thème Monokai pour Vue Flow */
.vue-flow-monokai {
  background-color: #272822;
}

.vue-flow-monokai .vue-flow__background {
  background-color: #272822;
}

.vue-flow-monokai .vue-flow__controls {
  background: #272822;
  border: 1px solid #75715E;
  border-radius: 8px;
  box-shadow: 0 2px 8px rgba(0, 0, 0, 0.3);
}

.vue-flow-monokai .vue-flow__controls-button {
  background: #272822;
  border-color: #75715E;
  color: #F8F8F2;
  fill: #F8F8F2;
}

.vue-flow-monokai .vue-flow__controls-button:hover {
  background: #3E3D32;
}

.vue-flow-monokai .vue-flow__controls-button svg {
  fill: #F8F8F2;
}

.vue-flow-monokai .vue-flow__minimap {
  background: #1E1F1C;
  border: 1px solid #75715E;
  border-radius: 8px;
}

.vue-flow-monokai .vue-flow__edge-path {
  stroke: #56A7FF;
}

.vue-flow-monokai .vue-flow__edge.selected .vue-flow__edge-path {
  stroke: #66D9EF;
  stroke-width: 3;
}

.vue-flow-monokai .vue-flow__connection-line {
  stroke: #A6E22E;
  stroke-width: 2;
}

.vue-flow-monokai .vue-flow__handle {
  border-radius: 50%;
}

.vue-flow-monokai .vue-flow__selection {
  background: rgba(102, 217, 239, 0.1);
  border: 1px solid #66D9EF;
}

/* Attribution panel cachée */
.vue-flow-monokai .vue-flow__attribution {
  display: none;
}
</style>
