// FLUJOS_APP.js ubicado en /var/www/flujos/FLUJOS/BACK_BACK/

require('dotenv').config(); // Cargar variables de entorno desde .env

const express = require('express');
const path = require('path');
const bodyParser = require('body-parser');
const helmet = require('helmet');
const { MongoClient } = require('mongodb');

const app = express();
const port = process.env.PORT || 3000;

// Configurar Helmet con CSP personalizado
app.use(
  helmet.contentSecurityPolicy({
    directives: {
      defaultSrc: ["'self'"],
      scriptSrc: [
        "'self'",
        "'unsafe-inline'",
        'https://unpkg.com',
        'https://cdnjs.cloudflare.com',
        'https://fonts.googleapis.com',
        'https://fonts.gstatic.com',
      ],
      styleSrc: ["'self'", "'unsafe-inline'", 'https://fonts.googleapis.com'],
      imgSrc: ["'self'", 'data:'],
      connectSrc: ["'self'", 'ws://localhost:3000'],
      fontSrc: ["'self'", 'https://fonts.gstatic.com'],
    },
  })
);

app.use(bodyParser.json());

// **Definir primero las rutas de la API**

app.get('/api/data', async (req, res) => {
  console.log('Solicitud recibida en /api/data');
  try {
    // Asegurarse de que la conexión a la base de datos está establecida
    if (!db) {
      res.status(500).json({ error: 'No hay conexión a la base de datos' });
      return;
    }

    // Acceder a las colecciones necesarias
    const wikipediaCollection = db.collection('wikipedia');
    const noticiasCollection = db.collection('noticias');
    const torrentsCollection = db.collection('torrents');
    const comparacionesCollection = db.collection('comparaciones');

    // Obtener los parámetros de consulta del cliente
    const { tema, subtematica, palabraClave, fechaInicio, fechaFin, nodos, complejidad } = req.query;
    console.log('Parámetros de consulta:', req.query);

    // Validar que el parámetro 'tema' esté presente
    if (!tema) {
      res.status(400).json({ error: 'El parámetro "tema" es obligatorio' });
      return;
    }

    // Construir la consulta para obtener los nodos (noticias, wikipedia y torrents)
    let nodesQuery = {
      tema: tema, // Usar el tema proporcionado
    };
    if (subtematica) nodesQuery.subtema = subtematica;
    if (palabraClave)
      nodesQuery.texto = { $regex: palabraClave, $options: 'i' };
    if (fechaInicio && fechaFin) {
      nodesQuery.fecha = {
        $gte: new Date(fechaInicio),
        $lte: new Date(fechaFin),
      };
    }
    console.log('Consulta para nodos:', nodesQuery);

    // Obtener el límite de nodos (con un máximo para evitar sobrecarga)
    const nodosLimit = Math.min(parseInt(nodos) || 100, 500);

    // Ejecutar la consulta y obtener los resultados de las colecciones
    console.log('Ejecutando consulta para nodos en colecciones...');
    const [wikipediaNodes, noticiasNodes, torrentsNodes] = await Promise.all([
      wikipediaCollection.find(nodesQuery).limit(nodosLimit).toArray(),
      noticiasCollection.find(nodesQuery).limit(nodosLimit).toArray(),
      torrentsCollection.find(nodesQuery).limit(nodosLimit).toArray(),
    ]);
    console.log('Nodos de Wikipedia obtenidos:', wikipediaNodes.length);
    console.log('Nodos de Noticias obtenidos:', noticiasNodes.length);
    console.log('Nodos de Torrents obtenidos:', torrentsNodes.length);

    // Combinar los nodos de las colecciones
    const nodes = [...wikipediaNodes, ...noticiasNodes, ...torrentsNodes];
    console.log('Total de nodos combinados:', nodes.length);

    // Utilizar los nombres de archivo exactos como IDs de los nodos
    const formattedNodes = nodes.map((result) => ({
      id: result.archivo.trim(), // Utilizar el nombre de archivo exacto sin normalizar
      group: result.subtema || 'sin subtema',
      tema: result.tema || 'sin tema',
      content: result.texto || '',
      fecha: result.fecha || '',
    }));

    // Obtener los IDs de los nodos
    const nodeIds = formattedNodes.map(node => node.id);
    console.log('IDs de nodos:', nodeIds);

    // Leer el parámetro 'complejidad' de la query (que en tu front envías como % de similitud)
    const porcentajeSimilitudMin = parseFloat(complejidad) || 0;
    console.log('Porcentaje de similitud mínimo (desde complejidad):', porcentajeSimilitudMin);

    // Construir la consulta para obtener los enlaces relacionados con los nodos obtenidos
    const linksQuery = {
      porcentaje_similitud: { $gte: porcentajeSimilitudMin },
      noticia1: { $in: nodeIds },
      noticia2: { $in: nodeIds },
    };
    console.log('Consulta para enlaces:', linksQuery);

    // Ejecutar la consulta y obtener los enlaces
    console.log('Ejecutando consulta para enlaces...');
    const links = await comparacionesCollection.find(linksQuery).toArray();
    console.log('Enlaces obtenidos:', links.length);

    // Formatear los enlaces sin normalizar los IDs
    const formattedLinks = links.map((result) => ({
      source: result.noticia1.trim(),
      target: result.noticia2.trim(),
      value: result.porcentaje_similitud,
    }));

    // Enviar los datos al cliente en formato JSON
    res.json({ nodes: formattedNodes, links: formattedLinks });
    console.log('Datos enviados al cliente');
  } catch (error) {
    console.error('Error al obtener datos:', error);
    res.status(500).json({ error: 'Error al obtener datos' });
  }
});

// **Luego, definir las rutas de las páginas principales**
// Rutas para las páginas principales
app.get('/', (req, res) => {
  res.sendFile(path.join(__dirname, '../VISUALIZACION/public/index.html'));
});

app.get('/climate.html', (req, res) => {
  res.sendFile(path.join(__dirname, '../VISUALIZACION/public/climate.html'));
});

app.get('/glob-war.html', (req, res) => {
  res.sendFile(path.join(__dirname, '../VISUALIZACION/public/glob-war.html'));
});

app.get('/popl-up.html', (req, res) => {
  res.sendFile(path.join(__dirname, '../VISUALIZACION/public/popl-up.html'));
});

app.get('/int-sec.html', (req, res) => {
  res.sendFile(path.join(__dirname, '../VISUALIZACION/public/int-sec.html'));
});

app.get('/eco-corp.html', (req, res) => {
  res.sendFile(path.join(__dirname, '../VISUALIZACION/public/eco-corp.html'));
});

// **Después, configurar el middleware de archivos estáticos**

app.use(express.static(path.join(__dirname, '../VISUALIZACION/public')));

// Conexión a MongoDB usando variables de entorno
const mongoUrl = process.env.MONGO_URL || 'mongodb://localhost:27017';
const dbName = process.env.DB_NAME || 'FLUJOS_DATOS';

let db; // Variable para almacenar la conexión a la base de datos

// Función para conectar a MongoDB
async function connectToMongoDB() {
  try {
    const mongoClient = new MongoClient(mongoUrl, {
      useNewUrlParser: true,
      useUnifiedTopology: true,
    });
    await mongoClient.connect();
    db = mongoClient.db(dbName);
    console.log('Conectado a MongoDB');
  } catch (error) {
    console.error('Error al conectar a MongoDB:', error);
    process.exit(1); // Salir de la aplicación si no se puede conectar
  }
}

// Llamar a la función para conectar a MongoDB
connectToMongoDB();

// Iniciar el servidor escuchando en todas las interfaces
app.listen(port, '0.0.0.0', () => {
  console.log(`La aplicación está escuchando en http://localhost:${port}`);
});

// Manejar el cierre de la aplicación
process.on('SIGINT', async () => {
  if (db) {
    await db.close();
    console.log('Conexión a MongoDB cerrada');
  }
  process.exit(0);
});
