const DEVICE_TO_NODE = {
  server: 'hw-dell-pe',
  switch: 'net-catalyst',
  storage: 'storage-netapp',
  firewall: 'net-fortinet',
  router: 'net-junper-srx',
  loadbalancer: 'net-f5',
  san: 'storage-pure',
  pdu: 'infra-pdu',
  ups: 'infra-apc-ups',
  cooling: 'infra-cooling',
  patch_panel: 'infra-patch-panel',
  tape: 'storage-netapp',
  kvm: 'infra-rack',
  other: 'infra-rack'
};

const MANUFACTURER_NODE = {
  hpe: 'hw-hpe-dl',
  dell: 'hw-dell-pe',
  lenovo: 'hw-lenovo-ts',
  cisco: 'net-catalyst',
  juniper: 'net-junper-ex',
  arista: 'net-arista',
  netapp: 'storage-netapp',
  pure: 'storage-pure',
  fortinet: 'net-fortinet',
  f5: 'net-f5',
  palo: 'net-paloalto',
  nvidia: 'ai-nvidia',
  apc: 'infra-apc-ups'
};

const DIAGRAM_TYPE_LABELS = {
  data_architecture: 'Data Architectuur',
  network_topology: 'Netwerk Topologie',
  system_architecture: 'Systeem Architectuur',
  application_flow: 'Applicatie Flow',
  application_landscape: 'Applicatie Landschap'
};

function resolveNodeType(device) {
  const m = (device.manufacturer || '').toLowerCase();
  for (const [key, type] of Object.entries(MANUFACTURER_NODE)) {
    if (m.includes(key)) return type;
  }
  return DEVICE_TO_NODE[device.device_type] || 'hw-dell-pe';
}

function rackDevicesToNodes(devices, startX = 40, startY = 40) {
  return devices.map((d, i) => ({
    id: 'rd-' + d.id,
    type: resolveNodeType(d),
    x: startX + (i % 4) * 180,
    y: startY + Math.floor(i / 4) * 90,
    label: d.name,
    sub: (d.model || d.device_type || '').toString(),
    css: 'node-hw',
    w: 160,
    h: 48,
    ip: d.mgmt_ip || '',
    vendor: d.manufacturer || '',
    model: d.model || '',
    specs: d.specs || '',
    notes: d.notes || '',
    rack_device_id: d.id,
    layer: 'infra'
  }));
}

function parseDiagramJson(diagram) {
  let nodes = [];
  let edges = [];
  try {
    nodes = JSON.parse(diagram.nodes || '[]');
    edges = JSON.parse(diagram.edges || '[]');
  } catch (e) { /* ignore */ }
  if (!Array.isArray(nodes) && nodes && nodes.nodes) {
    edges = nodes.edges || [];
    nodes = nodes.nodes || [];
  }
  if (!Array.isArray(edges) && edges && edges.edges) {
    nodes = edges.nodes || nodes;
    edges = edges.edges || [];
  }
  if (!Array.isArray(nodes)) nodes = [];
  if (!Array.isArray(edges)) edges = [];
  return { nodes, edges };
}

function summarizeDiagram(diagram) {
  const { nodes, edges } = parseDiagramJson(diagram);
  const layers = {};
  nodes.forEach(n => {
    const layer = n.layer || (n.type || '').split('-')[0] || 'other';
    layers[layer] = (layers[layer] || 0) + 1;
  });
  const protocols = {};
  edges.forEach(e => {
    const p = e.protocol || 'unspecified';
    protocols[p] = (protocols[p] || 0) + 1;
  });
  return { nodes, edges, layers, protocols, nodeCount: nodes.length, edgeCount: edges.length };
}

function getLayerForCategory(catLabel) {
  const c = (catLabel || '').toLowerCase();
  if (c.includes('data bron') || c.includes('ingest') || c.includes('opslag') || c.includes('database')) return 'data';
  if (c.includes('microservice') || c.includes('apps')) return 'app';
  if (c.includes('api') || c.includes('messaging') || c.includes('queue')) return 'integration';
  if (c.includes('netwerk') || c.includes('compute / server') || c.includes('infrastructure') || c.includes('security') || c.includes('observability') || c.includes('ci/cd')) return 'infra';
  if (c.includes('ai')) return 'app';
  return 'other';
}

module.exports = {
  DEVICE_TO_NODE,
  DIAGRAM_TYPE_LABELS,
  resolveNodeType,
  rackDevicesToNodes,
  parseDiagramJson,
  summarizeDiagram,
  getLayerForCategory
};
