const express = require('express');
const router = express.Router();
const { getDb } = require('../db');
const { parseDiagramJson, summarizeDiagram, rackDevicesToNodes, DIAGRAM_TYPE_LABELS, buildStudioDemo, getWorkspaceTab } = require('../lib/rack-diagram');

function loadRackWorkspace(db, rackId) {
  const rack = db.prepare('SELECT r.*, c.name as client_name FROM racks r JOIN clients c ON c.id = r.client_id WHERE r.id = ?').get(rackId);
  if (!rack) return null;
  const rackDevices = db.prepare('SELECT * FROM rack_devices WHERE rack_id = ? ORDER BY position_u ASC').all(rackId);
  const linkedDiagrams = db.prepare('SELECT id, name, diagram_type, updated_at FROM data_diagrams WHERE rack_id = ? ORDER BY updated_at DESC').all(rackId);
  const flowDiagram = linkedDiagrams.find(d => d.diagram_type === 'application_flow') || null;
  const landscapeDiagram = linkedDiagrams.find(d => d.diagram_type === 'application_landscape') || null;
  return { rack, rackDevices, linkedDiagrams, flowDiagram, landscapeDiagram };
}

function renderArchEditor(res, opts) {
  const diagram = opts.diagram || null;
  const rack = opts.rack;
  const workspaceTab = opts.workspaceTab || (diagram ? getWorkspaceTab(diagram.diagram_type) : opts.defaultDiagramType === 'application_landscape' ? 'landscape' : 'flow');
  res.render('arch-editor', {
    diagram,
    clients: opts.clients,
    clientId: opts.clientId || (rack ? rack.client_id : null),
    rack,
    rackDevices: opts.rackDevices || [],
    linkedDiagrams: opts.linkedDiagrams || [],
    flowDiagram: opts.flowDiagram || null,
    landscapeDiagram: opts.landscapeDiagram || null,
    defaultDiagramType: opts.defaultDiagramType || null,
    workspaceTab,
    embed: !!opts.embed,
    error: opts.error || null
  });
}

router.get('/', (req, res) => {
  const db = getDb();
  const racks = db.prepare(`
    SELECT r.*, c.name as client_name,
      (SELECT COUNT(*) FROM rack_devices d WHERE d.rack_id = r.id) as device_count
    FROM racks r JOIN clients c ON c.id = r.client_id ORDER BY r.updated_at DESC
  `).all();
  res.render('racks-list', { racks });
});

router.get('/new', (req, res) => {
  const db = getDb();
  const clients = db.prepare('SELECT id, name FROM clients ORDER BY name').all();
  res.render('racks-form', { rack: null, clients, selected: req.query.client_id ? parseInt(req.query.client_id, 10) : null, error: null });
});

router.get('/new/:clientId', (req, res) => {
  const db = getDb();
  const clients = db.prepare('SELECT id, name FROM clients ORDER BY name').all();
  res.render('racks-form', { rack: null, clients, selected: parseInt(req.params.clientId), error: null });
});

router.post('/new', (req, res) => {
  const db = getDb();
  const { client_id, name, location, datacenter, total_units, notes } = req.body;
  if (!name || !client_id) return res.redirect('/racks');
  db.prepare('INSERT INTO racks (client_id, name, location, datacenter, total_units, notes) VALUES (?,?,?,?,?,?)')
    .run(client_id, name, location, datacenter, total_units || 42, notes);
  res.redirect('/racks');
});

router.get('/:id', (req, res) => {
  const db = getDb();
  const ws = loadRackWorkspace(db, req.params.id);
  if (!ws) return res.redirect('/racks');
  const hardwareLibrary = require('../data/hardware-library');
  if (req.query.embed === '1') {
    return res.render('racks-view', {
      ...ws,
      devices: ws.rackDevices,
      hardwareLibrary,
      embed: true,
      workspaceTab: 'rack'
    });
  }
  res.render('racks-view', {
    rack: ws.rack,
    devices: ws.rackDevices,
    hardwareLibrary,
    linkedDiagrams: ws.linkedDiagrams,
    flowDiagram: ws.flowDiagram,
    landscapeDiagram: ws.landscapeDiagram,
    workspaceTab: 'rack',
    embed: false
  });
});

router.get('/:id/edit', (req, res) => {
  const db = getDb();
  const rack = db.prepare('SELECT * FROM racks WHERE id = ?').get(req.params.id);
  if (!rack) return res.redirect('/racks');
  const clients = db.prepare('SELECT id, name FROM clients ORDER BY name').all();
  res.render('racks-form', { rack, clients, selected: rack.client_id, error: null });
});

router.post('/:id/edit', (req, res) => {
  const db = getDb();
  const { name, location, datacenter, total_units, notes } = req.body;
  db.prepare("UPDATE racks SET name=?, location=?, datacenter=?, total_units=?, notes=?, updated_at=datetime('now') WHERE id=?")
    .run(name, location, datacenter, total_units, notes, req.params.id);
  res.redirect('/racks/' + req.params.id);
});

router.post('/:id/delete', (req, res) => {
  const db = getDb();
  db.prepare('DELETE FROM racks WHERE id = ?').run(req.params.id);
  res.redirect('/racks');
});

router.post('/:id/devices', (req, res) => {
  const db = getDb();
  const { name, device_type, model, manufacturer, position_u, height_u, specs, mgmt_ip, notes, status } = req.body;
  if (!name) return res.redirect('/racks/' + req.params.id);
  db.prepare('INSERT INTO rack_devices (rack_id, name, device_type, model, manufacturer, position_u, height_u, specs, mgmt_ip, notes, status) VALUES (?,?,?,?,?,?,?,?,?,?,?)')
    .run(req.params.id, name, device_type || 'server', model, manufacturer, parseInt(position_u), parseInt(height_u) || 1, specs, mgmt_ip, notes, status || 'active');
  res.redirect('/racks/' + req.params.id);
});

router.post('/devices/:deviceId/edit', (req, res) => {
  const db = getDb();
  const { name, device_type, model, manufacturer, position_u, height_u, specs, mgmt_ip, notes, status } = req.body;
  const device = db.prepare('SELECT rack_id FROM rack_devices WHERE id = ?').get(req.params.deviceId);
  if (!device) return res.redirect('/racks');
  db.prepare("UPDATE rack_devices SET name=?, device_type=?, model=?, manufacturer=?, position_u=?, height_u=?, specs=?, mgmt_ip=?, notes=?, status=?, updated_at=datetime('now') WHERE id=?")
    .run(name, device_type, model, manufacturer, position_u, height_u, specs, mgmt_ip, notes, status, req.params.deviceId);
  res.redirect('/racks/' + device.rack_id);
});

router.post('/devices/:deviceId/delete', (req, res) => {
  const db = getDb();
  const device = db.prepare('SELECT rack_id FROM rack_devices WHERE id = ?').get(req.params.deviceId);
  if (device) {
    db.prepare('DELETE FROM rack_devices WHERE id = ?').run(req.params.deviceId);
    res.redirect('/racks/' + device.rack_id);
  } else {
    res.redirect('/racks');
  }
});

router.get('/:id/flow/new', (req, res) => {
  const db = getDb();
  const ws = loadRackWorkspace(db, req.params.id);
  if (!ws) return res.redirect('/racks');
  const clients = db.prepare('SELECT id, name FROM clients ORDER BY name').all();
  renderArchEditor(res, {
    ...ws,
    clients,
    diagram: null,
    defaultDiagramType: 'application_flow',
    workspaceTab: 'flow',
    embed: req.query.embed === '1'
  });
});

router.get('/:id/landscape/new', (req, res) => {
  const db = getDb();
  const ws = loadRackWorkspace(db, req.params.id);
  if (!ws) return res.redirect('/racks');
  const clients = db.prepare('SELECT id, name FROM clients ORDER BY name').all();
  renderArchEditor(res, {
    ...ws,
    clients,
    diagram: null,
    defaultDiagramType: 'application_landscape',
    workspaceTab: 'landscape',
    embed: req.query.embed === '1'
  });
});

router.get('/:id/diagram/:diagramId', (req, res) => {
  const db = getDb();
  const ws = loadRackWorkspace(db, req.params.id);
  if (!ws) return res.redirect('/racks');
  const diagram = db.prepare('SELECT d.*, c.name as client_name FROM data_diagrams d JOIN clients c ON c.id = d.client_id WHERE d.id = ? AND d.rack_id = ?').get(req.params.diagramId, req.params.id);
  if (!diagram) return res.redirect('/racks/' + req.params.id);
  const clients = db.prepare('SELECT id, name FROM clients ORDER BY name').all();
  renderArchEditor(res, {
    ...ws,
    clients,
    diagram,
    workspaceTab: getWorkspaceTab(diagram.diagram_type),
    embed: req.query.embed === '1'
  });
});

router.get('/:id/studio', (req, res) => {
  const db = getDb();
  const ws = loadRackWorkspace(db, req.params.id);
  if (!ws) return res.redirect('/racks');
  res.render('rack-studio', { ...ws, workspaceTab: 'studio' });
});

router.post('/:id/studio/demo', (req, res) => {
  const db = getDb();
  const ws = loadRackWorkspace(db, req.params.id);
  if (!ws) return res.status(404).json({ error: 'Rack not found' });
  const demo = buildStudioDemo(ws.rack, ws.rackDevices);
  let flowId = ws.flowDiagram ? ws.flowDiagram.id : null;
  let landscapeId = ws.landscapeDiagram ? ws.landscapeDiagram.id : null;
  if (flowId) {
    db.prepare("UPDATE data_diagrams SET name=?, nodes=?, edges=?, updated_at=datetime('now') WHERE id=?")
      .run(demo.flow.name, demo.flow.nodes, demo.flow.edges, flowId);
  } else {
    const r = db.prepare('INSERT INTO data_diagrams (client_id, name, description, diagram_type, nodes, edges, rack_id) VALUES (?,?,?,?,?,?,?)')
      .run(ws.rack.client_id, demo.flow.name, 'Studio demo flow', 'application_flow', demo.flow.nodes, demo.flow.edges, ws.rack.id);
    flowId = r.lastInsertRowid;
  }
  if (landscapeId) {
    db.prepare("UPDATE data_diagrams SET name=?, nodes=?, edges=?, updated_at=datetime('now') WHERE id=?")
      .run(demo.landscape.name, demo.landscape.nodes, demo.landscape.edges, landscapeId);
  } else {
    const r = db.prepare('INSERT INTO data_diagrams (client_id, name, description, diagram_type, nodes, edges, rack_id) VALUES (?,?,?,?,?,?,?)')
      .run(ws.rack.client_id, demo.landscape.name, 'Studio demo landschap', 'application_landscape', demo.landscape.nodes, demo.landscape.edges, ws.rack.id);
    landscapeId = r.lastInsertRowid;
  }
  res.json({ success: true, flowId, landscapeId, redirect: '/racks/' + ws.rack.id + '/studio' });
});

router.get('/:id/devices.json', (req, res) => {
  const db = getDb();
  const rack = db.prepare('SELECT * FROM racks WHERE id = ?').get(req.params.id);
  if (!rack) return res.status(404).json({ error: 'Rack not found' });
  const devices = db.prepare('SELECT * FROM rack_devices WHERE rack_id = ? ORDER BY position_u ASC').all(req.params.id);
  res.json({ rack, devices, nodes: rackDevicesToNodes(devices) });
});

router.get('/:id/report', (req, res) => {
  const db = getDb();
  const rack = db.prepare('SELECT r.*, c.name as client_name FROM racks r JOIN clients c ON c.id = r.client_id WHERE r.id = ?').get(req.params.id);
  if (!rack) return res.redirect('/racks');
  const devices = db.prepare('SELECT * FROM rack_devices WHERE rack_id = ? ORDER BY position_u ASC').all(req.params.id);
  const diagrams = db.prepare(`
    SELECT d.*, c.name as client_name FROM data_diagrams d
    JOIN clients c ON c.id = d.client_id WHERE d.rack_id = ?
    ORDER BY CASE d.diagram_type WHEN 'application_flow' THEN 0 WHEN 'application_landscape' THEN 1 ELSE 2 END, d.updated_at DESC
  `).all(req.params.id);
  const diagramSummaries = diagrams.map(d => ({
    ...d,
    ...summarizeDiagram(d),
    typeLabel: DIAGRAM_TYPE_LABELS[d.diagram_type] || d.diagram_type
  }));
  const usedU = devices.reduce((s, d) => s + (d.height_u || 1), 0);
  res.render('rack-infra-report', {
    rack,
    devices,
    diagrams: diagramSummaries,
    usedU,
    typeLabels: DIAGRAM_TYPE_LABELS
  });
});

module.exports = router;
