/**
 * Store Pinia pour l'éditeur d'architecture Vue Flow
 * Gère les noeuds, edges, sélection, sauvegarde/chargement
 */
import { defineStore } from 'pinia'
import { ref, computed } from 'vue'
import axios from 'axios'
import {
  migrateData,
  nodeToSaveFormat,
  edgeToSaveFormat,
} from '@/composables/useArchitectureMigration'

/** Définition des outils de la palette (6 types, world supprimé) */
export const TOOL_DEFINITIONS = [
  { id: 'home', label: 'home', type: 'container', icon: '', borderColor: '#8F6FE3', color: '#BDA8F7' },
  { id: 'computer', label: 'computer', type: 'device', icon: '', borderColor: '#B5B5B5', color: '#E6E6E6' },
  { id: 'network', label: 'network', type: 'network', icon: '🌐', borderColor: '#56A7FF', color: '#9BC8FF' },
  { id: 'room', label: 'room', type: 'container', icon: '', borderColor: '#C8A08A', color: '#E6CDBE' },
  { id: 'vm', label: 'vm', type: 'vm', icon: '', borderColor: '#62D36E', color: '#9BE3A4' },
  { id: 'service', label: 'service', type: 'service', icon: '', borderColor: '#F0A33A', color: '#F7C37B' },
]

/** Valeurs par défaut d'un edge */
const DEFAULT_EDGE_STYLE = {
  color: '#56A7FF',
  width: 2,
  dash: 'solid',
  startCap: 'none',
  endCap: 'none',
}

export const useArchitectureStore = defineStore('architecture', () => {
  // --- État ---
  const nodes = ref([])
  const edges = ref([])
  const selectedNodeId = ref(null)
  const selectedEdgeId = ref(null)
  const iconList = ref([])

  // --- Computed ---
  const selectedNode = computed(() => {
    if (!selectedNodeId.value) return null
    return nodes.value.find(n => n.id === selectedNodeId.value) || null
  })

  const selectedEdge = computed(() => {
    if (!selectedEdgeId.value) return null
    return edges.value.find(e => e.id === selectedEdgeId.value) || null
  })

  // --- Chargement / Sauvegarde ---

  async function loadWorld() {
    try {
      const response = await axios.get('/api/architecture/world')
      const migrated = migrateData(response.data)
      nodes.value = migrated.nodes
      edges.value = migrated.edges
      console.log(`[Architecture] Chargé : ${nodes.value.length} nodes, ${edges.value.length} edges`)
    } catch (error) {
      console.error('[Architecture] Erreur chargement:', error)
      nodes.value = []
      edges.value = []
    }
  }

  async function saveWorld() {
    try {
      const data = {
        nodes: nodes.value.map(nodeToSaveFormat),
        edges: edges.value.map(edgeToSaveFormat),
        version: 2,
      }
      await axios.post('/api/architecture/world', data)
      console.log(`[Architecture] Sauvegardé : ${data.nodes.length} nodes, ${data.edges.length} edges`)
    } catch (error) {
      console.error('[Architecture] Erreur sauvegarde:', error)
    }
  }

  // --- CRUD Nodes ---

  function addNode(toolId, position, parentNodeId = null) {
    const tool = TOOL_DEFINITIONS.find(t => t.id === toolId)
    if (!tool) return null

    const ts = Date.now()
    const rnd = Math.random().toString(36).slice(2, 6)
    const instanceId = `${tool.id}-${ts}-${rnd}`

    const newNode = {
      id: instanceId,
      type: 'arch-node',
      position: { x: Math.round(position.x), y: Math.round(position.y) },
      style: { width: '120px', height: '44px' },
      zIndex: 1,
      draggable: true,
      // Nesting : si parentNodeId, le noeud est contraint dans son parent
      ...(parentNodeId ? { parentNode: parentNodeId, extent: 'parent', expandParent: true } : {}),
      data: {
        nodeType: tool.id,
        instanceId,
        id: tool.id,
        name: tool.label,
        label: tool.label,
        type: tool.type,
        icon: tool.icon,
        iconSize: 16,
        borderColor: tool.borderColor,
        fillColor: 'transparent',
        color: tool.color,
        opacity: 1,
        borderWidth: 2,
        borderStyle: 'solid',
        fontColor: '#E6E6E6',
        fontSize: 14,
        connectTop: 0,
        connectBottom: 0,
        connectLeft: 0,
        connectRight: 0,
        connectorColor: '#B5B5B5',
        connectorSize: 12,
        connectorStrokeColor: '#1E1F1C',
        ipAddress: '',
        ipData: null,
        online: false,
        parentId: parentNodeId || '',
        childrenIds: [],
        parent: '',
        room: '',
        locked: false,
      }
    }

    // Ajouter l'enfant dans la liste childrenIds du parent
    if (parentNodeId) {
      const parentIdx = nodes.value.findIndex(n => n.id === parentNodeId)
      if (parentIdx !== -1) {
        const parentNode = nodes.value[parentIdx]
        const childrenIds = [...(parentNode.data?.childrenIds || []), instanceId]
        nodes.value[parentIdx] = {
          ...parentNode,
          data: { ...parentNode.data, childrenIds }
        }
      }
    }

    nodes.value = [...nodes.value, newNode]
    selectedNodeId.value = instanceId
    selectedEdgeId.value = null
    return newNode
  }

  function updateNodeData(nodeId, field, value) {
    const idx = nodes.value.findIndex(n => n.id === nodeId)
    if (idx === -1) return
    const node = nodes.value[idx]
    if (field !== 'locked' && node.data?.locked) return

    // Champs spéciaux qui vivent hors de data
    if (field === 'position.x' || field === 'position.y') {
      const axis = field.split('.')[1]
      nodes.value[idx] = {
        ...node,
        position: { ...node.position, [axis]: Number(value) }
      }
      return
    }
    if (field === 'width' || field === 'height') {
      nodes.value[idx] = {
        ...node,
        style: { ...node.style, [field]: `${value}px` }
      }
      return
    }
    if (field === 'zIndex') {
      nodes.value[idx] = { ...node, zIndex: Number(value) }
      return
    }
    if (field === 'locked') {
      nodes.value[idx] = {
        ...node,
        draggable: !value,
        data: { ...node.data, locked: value }
      }
      return
    }

    // Champ standard dans data
    nodes.value[idx] = {
      ...node,
      data: { ...node.data, [field]: value }
    }
  }

  function removeNode(nodeId) {
    // Supprimer les edges connectés
    edges.value = edges.value.filter(e => e.source !== nodeId && e.target !== nodeId)
    // Détacher les enfants du noeud supprimé (les rendre top-level)
    nodes.value = nodes.value.map(n => {
      if (n.parentNode === nodeId) {
        const { parentNode, extent, expandParent, ...rest } = n
        return { ...rest, data: { ...n.data, parentId: '' } }
      }
      if (n.data?.parentId === nodeId) {
        return { ...n, data: { ...n.data, parentId: '' } }
      }
      if (Array.isArray(n.data?.childrenIds) && n.data.childrenIds.includes(nodeId)) {
        return { ...n, data: { ...n.data, childrenIds: n.data.childrenIds.filter(id => id !== nodeId) } }
      }
      return n
    })
    nodes.value = nodes.value.filter(n => n.id !== nodeId)
    if (selectedNodeId.value === nodeId) selectedNodeId.value = null
  }

  // --- CRUD Edges ---

  function addEdge(connection) {
    const id = `edge-${Date.now()}-${Math.random().toString(36).slice(2, 6)}`
    const newEdge = {
      id,
      source: connection.source,
      target: connection.target,
      sourceHandle: connection.sourceHandle,
      targetHandle: connection.targetHandle,
      type: 'default',
      style: {
        stroke: DEFAULT_EDGE_STYLE.color,
        strokeWidth: DEFAULT_EDGE_STYLE.width,
      },
      data: { ...DEFAULT_EDGE_STYLE },
    }
    edges.value = [...edges.value, newEdge]
    return newEdge
  }

  function updateEdgeData(edgeId, field, value) {
    const idx = edges.value.findIndex(e => e.id === edgeId)
    if (idx === -1) return

    const edge = edges.value[idx]
    const newData = { ...edge.data, [field]: value }

    // Mettre à jour le style SVG en conséquence
    const newStyle = {
      stroke: newData.color || '#56A7FF',
      strokeWidth: newData.width || 2,
    }
    if (newData.dash && newData.dash !== 'solid') {
      newStyle.strokeDasharray = newData.dash === 'dashed' ? '6 4' : '2 4'
    }

    edges.value[idx] = {
      ...edge,
      style: newStyle,
      data: newData,
    }
  }

  function removeEdge(edgeId) {
    edges.value = edges.value.filter(e => e.id !== edgeId)
    if (selectedEdgeId.value === edgeId) selectedEdgeId.value = null
  }

  // --- Sélection ---

  function selectNode(nodeId) {
    selectedNodeId.value = nodeId
    selectedEdgeId.value = null
  }

  function selectEdge(edgeId) {
    selectedEdgeId.value = edgeId
    selectedNodeId.value = null
  }

  function clearSelection() {
    selectedNodeId.value = null
    selectedEdgeId.value = null
  }

  // --- IP Integration ---

  async function fetchIpData(nodeId) {
    const node = nodes.value.find(n => n.id === nodeId)
    if (!node || !node.data?.ipAddress) return

    try {
      const response = await axios.get(`/api/ips/${encodeURIComponent(node.data.ipAddress)}`)
      const ipData = response.data

      const updates = {
        ipData,
        name: ipData.name || node.data.name,
        label: ipData.name || node.data.label,
        id: ipData.ip || node.data.id,
        type: ipData.vm ? 'vm' : node.data.type,
        room: ipData.location || node.data.room,
        parent: ipData.host || node.data.parent,
        icon: ipData.icon_filename || node.data.icon,
        online: ipData.last_status === 'online',
      }

      const idx = nodes.value.findIndex(n => n.id === nodeId)
      if (idx !== -1) {
        nodes.value[idx] = {
          ...nodes.value[idx],
          data: { ...nodes.value[idx].data, ...updates }
        }
      }
    } catch (error) {
      console.error(`[Architecture] Erreur fetch IP ${node.data.ipAddress}:`, error)
      updateNodeData(nodeId, 'ipData', null)
    }
  }

  // --- Icônes ---

  async function fetchIcons() {
    try {
      const response = await axios.get('/api/ips/icons')
      iconList.value = Array.isArray(response.data?.icons) ? response.data.icons : []
    } catch {
      iconList.value = []
    }
  }

  return {
    // État
    nodes,
    edges,
    selectedNodeId,
    selectedEdgeId,
    iconList,
    // Computed
    selectedNode,
    selectedEdge,
    // Chargement
    loadWorld,
    saveWorld,
    // Nodes
    addNode,
    updateNodeData,
    removeNode,
    // Edges
    addEdge,
    updateEdgeData,
    removeEdge,
    // Sélection
    selectNode,
    selectEdge,
    clearSelection,
    // IP
    fetchIpData,
    fetchIcons,
  }
})
