// server.js
require('dotenv').config();  // solo una vez

const express = require('express');
const cors = require('cors');
const { Pool } = require('pg');
const ExcelJS = require('exceljs');
const PDFDocument = require('pdfkit');
const fsPromises = require('fs').promises;
const { crearLibroAutorizacion } = require('./plantilla_autorizacion');
const path = require('path');
const os = require('os');
const { execFile } = require('child_process');
const multer = require('multer');
const bcrypt = require('bcryptjs');
const jwt = require('jsonwebtoken');

const JWT_SECRET = process.env.JWT_SECRET || 'secreto-salud-ut-2025';
const JWT_EXPIRES_IN = process.env.JWT_EXPIRES_IN || '24h';

// Multer: guardamos el archivo en memoria y luego lo escribimos a disco
const upload = multer({
  storage: multer.memoryStorage(),
  limits: {
    fileSize: 50 * 1024 * 1024, // 50 MB por si el Excel es grande
  },
});

// Path de LibreOffice desde .env (con valor por defecto)
const sofficePath =
  process.env.SOFFICE_PATH || 'C:\\Program Files\\LibreOffice\\program\\soffice.exe';

// Config DB usando .env
const pool = new Pool({
  host: process.env.DB_HOST || 'localhost',
  user: process.env.DB_USER || 'postgres',
  port: Number(process.env.DB_PORT) || 5432,
  password: process.env.DB_PASSWORD || '1234',
  database: process.env.DB_NAME || 'saludut',
});

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

app.use(cors());

// IMPORTANTE: subir límite de JSON, pero esto solo afecta a peticiones application/json
app.use(
  express.json({
    limit: '50mb',
  })
);

app.use(
  express.urlencoded({
    extended: true,
    limit: '50mb',
  })
);


// Middleware para verificar token JWT
const verificarToken = (req, res, next) => {
  const token = req.headers['authorization']?.replace('Bearer ', '');
  
  if (!token) {
    return res.status(401).json({ error: 'Token no proporcionado' });
  }

  try {
    const decoded = jwt.verify(token, JWT_SECRET);
    req.usuario = decoded;
    next();
  } catch (error) {
    return res.status(401).json({ error: 'Token inválido o expirado' });
  }
};

// Middleware para verificar rol específico
const verificarRol = (rolPermitido) => {
  return (req, res, next) => {
    if (req.usuario.nombre_rol !== rolPermitido) {
      return res.status(403).json({ error: 'No tienes permisos para esta acción' });
    }
    next();
  };
};

// Middleware para verificar si es administrador
const esAdministrador = verificarRol('administrador');

// Middleware para verificar si puede generar autorizaciones
const puedeGenerarAutorizaciones = (req, res, next) => {
  if (req.usuario.nombre_rol !== 'administrador' && req.usuario.nombre_rol !== 'administrativo_sede') {
    return res.status(403).json({ error: 'No tienes permisos para generar autorizaciones' });
  }
  next();
};

// Middleware para verificar acceso por sede (administrativos solo pueden ver de su sede)
const verificarAccesoSede = async (req, res, next) => {
  // Si es administrador, tiene acceso a todo
  if (req.usuario.nombre_rol === 'administrador') {
    return next();
  }

  // Si es administrativo, verificar que tenga acceso a la sede del paciente
  const { interno } = req.query;
  if (!interno) {
    return res.status(400).json({ error: 'Se requiere el parámetro interno' });
  }

  try {
    const sql = `
      SELECT 1 FROM usuario_sede us
      JOIN ingreso i ON us.codigo_establecimiento = i.codigo_establecimiento
      WHERE us.id_usuario = $1 AND i.interno = $2
    `;
    
    const { rows } = await pool.query(sql, [req.usuario.id_usuario, interno]);
    
    if (rows.length === 0) {
      return res.status(403).json({ error: 'No tienes permisos para acceder a este interno' });
    }

    next();
  } catch (error) {
    console.error('Error verificando acceso a sede:', error);
    return res.status(500).json({ error: 'Error en el servidor' });
  }
};

/**
 * GET /api/pacientes
 * Query params:
 *  - numero_documento
 *  - interno
 *  - nombre
 */
app.get('/api/pacientes', verificarToken, verificarAccesoSede, async (req, res) => {
  const { numero_documento, interno, nombre } = req.query;

  if (!numero_documento && !interno && !nombre) {
    return res.status(400).json({
      error: 'Debe enviar al menos uno: numero_documento, interno o nombre',
    });
  }

  let sql = `
    SELECT 
      p.interno,
      p.tipo_documento,
      p.numero_documento,
      p.primer_apellido,
      p.segundo_apellido,
      p.primer_nombre,
      p.segundo_nombre,
      p.fecha_nacimiento,
      p.edad,
      p.sexo,
      i.codigo_establecimiento,
      e.nombre_establecimiento,
      i.estado,
      i.fecha_ingreso,
      i.tiempo_reclusion
    FROM paciente p
    LEFT JOIN ingreso i ON p.interno = i.interno
    LEFT JOIN establecimiento e ON i.codigo_establecimiento = e.codigo_establecimiento
    WHERE 1 = 1
  `;

  const params = [];

  if (numero_documento) {
    params.push(`%${numero_documento}%`);
    sql += ` AND p.numero_documento ILIKE $${params.length}`;
  }

  if (interno) {
    params.push(`%${interno}%`);
    sql += ` AND p.interno ILIKE $${params.length}`;
  }

  if (nombre) {
    params.push(`%${nombre}%`);
    sql += `
      AND (
        (p.primer_nombre || ' ' || COALESCE(p.segundo_nombre, '') || ' ' ||
         p.primer_apellido || ' ' || COALESCE(p.segundo_apellido, '')
        ) ILIKE $${params.length}
      )
    `;
  }

  sql += ' ORDER BY p.interno LIMIT 50;';

  try {
    const { rows } = await pool.query(sql, params);
    res.json(rows);
  } catch (err) {
    console.error('Error en consulta:', err.message);
    res.status(500).json({ error: 'Error consultando la base de datos' });
  }
});

/**
 * GET /api/ips-por-interno?interno=1007362
 * Busca el departamento del establecimiento del interno
 * y devuelve las IPS de ese departamento (o Bogotá).
 */
app.get('/api/ips-por-interno', verificarToken, verificarAccesoSede, async (req, res) => {
  const { interno } = req.query;

  if (!interno) {
    return res.status(400).json({ error: 'Falta parámetro interno' });
  }

  try {
    // 1) Obtener el departamento y municipio del establecimiento donde está el interno
    const qDepto = `
      SELECT e.epc_departamento, e.epc_ciudad
      FROM ingreso i
      JOIN establecimiento e
        ON i.codigo_establecimiento = e.codigo_establecimiento
      WHERE i.interno = $1
      LIMIT 1;
    `;
    const deptoRes = await pool.query(qDepto, [interno]);

    if (deptoRes.rows.length === 0) {
      return res.json([]); // interno sin ingreso o sin establecimiento
    }

    const departamento = (deptoRes.rows[0].epc_departamento || '').trim();
    const municipioRaw = (deptoRes.rows[0].epc_ciudad || '').trim();
    const municipioUpper = municipioRaw.toUpperCase();

    // Detectar Bogotá aunque venga como "BOGOTA D.C.", "BOGOTA DISTRITO CAPITAL", etc.
    const esBogota =
      municipioUpper.includes('BOGOTA') ||
      departamento.toUpperCase().includes('BOGOTA');

    let qIps;
    let params;

    if (esBogota) {
      // Para Bogotá buscamos por "BOGOTA" en municipio o departamento
      qIps = `
        SELECT id_ips, nombre_ips, direccion, telefono, departamento, municipio
        FROM ips
        WHERE municipio ILIKE $1
           OR departamento ILIKE $1
        ORDER BY nombre_ips;
      `;
      params = ['%BOGOTA%'];
    } else {
      // Resto del país: por departamento
      qIps = `
        SELECT id_ips, nombre_ips, direccion, telefono, departamento, municipio
        FROM ips
        WHERE departamento ILIKE $1
        ORDER BY nombre_ips;
      `;
      params = [`%${departamento}%`];
    }

    // (Opcional) log para depurar si algo raro pasa
    console.log('[IPS-por-interno] interno', interno,
                'depto:', departamento,
                'muni:', municipioRaw,
                'esBogota?', esBogota);

    const { rows } = await pool.query(qIps, params);
    res.json(rows);
  } catch (err) {
    console.error('Error en /api/ips-por-interno:', err.message);
    res.status(500).json({ error: 'Error consultando IPS' });
  }
});



/**
 * GET /api/autorizantes
 * Lista las personas que pueden autorizar (activos).
 */
app.get('/api/autorizantes', async (_req, res) => {
  try {
    const sql = `
      SELECT numero_documento, tipo_documento, nombre, telefono, cargo, activo
      FROM autorizante
      WHERE activo = true
      ORDER BY nombre;
    `;
    const { rows } = await pool.query(sql);
    res.json(rows);
  } catch (err) {
    console.error('Error en /api/autorizantes:', err.message);
    res.status(500).json({ error: 'Error consultando autorizantes' });
  }
});

/**
 * POST /api/autorizaciones
 * Body JSON:
 * {
 *   "interno": "1007362",
 *   "id_ips": 15,
 *   "numero_documento_autorizante": 12345678,
 *   "observacion": "Consulta oftalmología",
 *   "fecha_autorizacion": "2025-11-25"  // opcional
 * }
 */
app.post('/api/autorizaciones', verificarToken, puedeGenerarAutorizaciones, async (req, res) => {
  const {
    interno,
    id_ips,
    numero_documento_autorizante,
    observacion,
    fecha_autorizacion,
  } = req.body;

  if (!interno || !id_ips || !numero_documento_autorizante) {
    return res.status(400).json({
      error: 'interno, id_ips y numero_documento_autorizante son obligatorios',
    });
  }

  // ... aquí va tu lógica de permisos por rol / sede ...

  try {
    const sql = `
      INSERT INTO autorizacion
      (interno, id_ips, numero_documento_autorizante, fecha_autorizacion, observacion)
      VALUES ($1, $2, $3, COALESCE($4::date, current_date), $5)
      RETURNING numero_autorizacion, fecha_autorizacion;
    `;

    const params = [
      interno,
      id_ips,
      numero_documento_autorizante,
      fecha_autorizacion || null,
      observacion || null,
    ];

    const { rows } = await pool.query(sql, params);
    res.status(201).json(rows[0]);
  } catch (err) {
    console.error('Error en /api/autorizaciones:', err.message);
    res.status(500).json({ error: 'Error guardando autorización' });
  }
});


/**
 * GET /api/autorizaciones?interno=1007362
 * Devuelve todas las autorizaciones del interno.
 */
app.get('/api/autorizaciones', async (req, res) => {
  const { interno } = req.query;

  if (!interno) {
    return res.status(400).json({ error: 'Falta parámetro interno' });
  }

  try {
    const sql = `
      SELECT 
        a.numero_autorizacion,
        a.fecha_autorizacion,
        a.observacion,
        ips.nombre_ips,
        ips.municipio,
        ips.departamento,
        aut.nombre AS nombre_autorizante
      FROM autorizacion a
      JOIN ips
        ON a.id_ips = ips.id_ips
      JOIN autorizante aut
        ON a.numero_documento_autorizante = aut.numero_documento
      WHERE a.interno = $1
      ORDER BY a.fecha_autorizacion DESC, a.numero_autorizacion DESC;
    `;

    const { rows } = await pool.query(sql, [interno]);
    res.json(rows);
  } catch (err) {
    console.error('Error en /api/autorizaciones:', err.message);
    res.status(500).json({ error: 'Error consultando autorizaciones' });
  }
});

// Endpoint para generar el Excel de autorizaciones
app.get('/api/generar-excel-autorizaciones', async (req, res) => {
  try {
    // Crear el workbook y la hoja de trabajo
    const workbook = new ExcelJS.Workbook();
    const worksheet = workbook.addWorksheet('Autorizaciones');

    // Agregar encabezados
    worksheet.columns = [
      { header: 'Número de Autorización', key: 'numero_autorizacion', width: 20 },
      { header: 'Interno', key: 'interno', width: 15 },
      { header: 'Nombre del paciente', key: 'nombre_paciente', width: 30 },
      { header: 'IPS', key: 'nombre_ips', width: 30 },
      { header: 'Fecha de autorización', key: 'fecha_autorizacion', width: 20 },
      { header: 'Observación', key: 'observacion', width: 50 },
      { header: 'Autoriza', key: 'autoriza', width: 20 },
    ];

    // Obtener autorizaciones de la base de datos
    const sql = `
      SELECT
        a.numero_autorizacion,
        p.interno,
        p.primer_nombre || ' ' || p.segundo_nombre || ' ' || p.primer_apellido || ' ' || p.segundo_apellido AS nombre_paciente,
        i.nombre_ips,
        a.fecha_autorizacion,
        a.observacion,
        aut.nombre AS autoriza
      FROM autorizacion a
      JOIN paciente p ON a.interno = p.interno
      JOIN ips i ON a.id_ips = i.id_ips
      JOIN autorizante aut ON a.numero_documento_autorizante = aut.numero_documento
    `;

    const { rows } = await pool.query(sql);

    // Agregar las filas a la hoja de trabajo
    rows.forEach(row => {
      worksheet.addRow({
        numero_autorizacion: row.numero_autorizacion,
        interno: row.interno,
        nombre_paciente: row.nombre_paciente,
        nombre_ips: row.nombre_ips,
        fecha_autorizacion: row.fecha_autorizacion,
        observacion: row.observacion,
        autoriza: row.autoriza,
      });
    });

    // Configurar la respuesta para que sea descargada como archivo Excel
    res.setHeader('Content-Type', 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet');
    res.setHeader('Content-Disposition', 'attachment; filename=autorizaciones.xlsx');

    // Escribir el archivo en la respuesta
    await workbook.xlsx.write(res);
    res.end();
  } catch (err) {
    console.error('Error al generar el Excel:', err.message);
    res.status(500).json({ error: 'Error al generar el archivo Excel' });
  }
});

/**
 * GET /api/generar-pdf-autorizacion?numero_autorizacion=2025-000123
 */
app.get('/api/generar-pdf-autorizacion', verificarToken, esAdministrador, async (req, res) => {
  const { numero_autorizacion } = req.query;

  if (!numero_autorizacion) {
    return res
      .status(400)
      .json({ error: 'Falta parámetro numero_autorizacion' });
  }

  try {
    const sql = `
      SELECT 
        a.numero_autorizacion,
        a.fecha_autorizacion,
        a.observacion,
        p.*,
        ips.nombre_ips,
        ips.nit,
        ips.direccion,
        ips.municipio,
        ips.departamento,
        aut.nombre   AS nombre_autorizante,
        aut.cargo    AS cargo_autorizante,
        aut.telefono AS tel_autorizante,
        e.nombre_establecimiento,
        e.epc_departamento
      FROM autorizacion a
      JOIN paciente p
        ON a.interno = p.interno
      JOIN ips
        ON a.id_ips = ips.id_ips
      JOIN autorizante aut
        ON a.numero_documento_autorizante = aut.numero_documento
      JOIN ingreso i
        ON a.interno = i.interno
      JOIN establecimiento e
        ON i.codigo_establecimiento = e.codigo_establecimiento
      WHERE a.numero_autorizacion = $1
      LIMIT 1;
    `;

    const { rows } = await pool.query(sql, [numero_autorizacion]);

    if (rows.length === 0) {
      return res.status(404).json({ error: 'Autorización no encontrada' });
    }

    const a = rows[0];

    // 1) Crear el Excel con tu plantilla (ya llenas todo lo de "base datos")
    const libro = await crearLibroAutorizacion(a);

    // 2) Guardar el XLSX en un archivo temporal
    const tmpDir = path.join(os.tmpdir(), 'salud_ut_autorizaciones');
    await fsPromises.mkdir(tmpDir, { recursive: true });

    const xlsxPath = path.join(tmpDir, `autorizacion_${numero_autorizacion}.xlsx`);
    const pdfPath  = path.join(tmpDir, `autorizacion_${numero_autorizacion}.pdf`);

    await libro.xlsx.writeFile(xlsxPath);

    // 3) Llamar a LibreOffice (soffice) para convertir XLSX -> PDF
    await new Promise((resolve, reject) => {
      execFile(
        sofficePath,
        [
          '--headless',
          '--convert-to', 'pdf',
          '--outdir', tmpDir,
          xlsxPath,
        ],
        (error, stdout, stderr) => {
          console.log('soffice stdout:', stdout);
          console.log('soffice stderr:', stderr);

          if (error) {
            return reject(error);
          }
          resolve();
        }
      );
    });

    // 4) Leer el PDF generado
    const pdfBuf = await fsPromises.readFile(pdfPath);

    // 5) Enviar el PDF al navegador
    res.setHeader('Content-Type', 'application/pdf');
    res.setHeader(
      'Content-Disposition',
      `attachment; filename="autorizacion_${numero_autorizacion}.pdf"`
    );
    res.end(pdfBuf);

    // 6) (Opcional) borrar archivos temporales
    try {
      await fsPromises.unlink(xlsxPath);
      await fsPromises.unlink(pdfPath);
    } catch (e) {
      console.warn('No se pudieron borrar temporales:', e.message);
    }
  } catch (err) {
    console.error('Error en /api/generar-pdf-autorizacion:', err);
    res.status(500).json({ error: 'Error generando el PDF' });
  }
});

app.post(
  '/api/cargar-excel-pacientes',
  verificarToken,
  esAdministrador,
  upload.single('archivo'),
  async (req, res) => {
    try {
      if (!req.file) {
        return res.status(400).json({ error: 'No se recibió archivo Excel' });
      }

      // 1) Guardar el Excel como pacientes.xlsx (mismo nombre que espera Python)
      const backendDir = __dirname;
      const excelPath = path.join(backendDir, 'pacientes.xlsx');
      await fsPromises.writeFile(excelPath, req.file.buffer);

      // 2) Ejecutar pacientes.py para generar los .sql
      const scriptPath = path.join(backendDir, 'pacientes.py');

      await new Promise((resolve, reject) => {
        execFile(
          process.env.PYTHON_PATH || 'python', // o 'python3'
          [scriptPath],
          { cwd: backendDir },
          (error, stdout, stderr) => {
            console.log('pacientes.py stdout:\n', stdout);
            console.error('pacientes.py stderr:\n', stderr);
            if (error) return reject(error);
            resolve();
          }
        );
      });

      // 3) Leer los .sql generados y ejecutarlos en una transacción
      const files = ['establecimiento.sql', 'paciente.sql', 'ingreso.sql'];

      console.log('Ejecutando scripts SQL generados...');
      await pool.query('BEGIN');

      for (const fname of files) {
        const fullPath = path.join(backendDir, fname);
        const sqlText = await fsPromises.readFile(fullPath, 'utf8');

        const lines = sqlText.split('\n');
        for (const line of lines) {
          const stmt = line.trim();
          if (!stmt || stmt.startsWith('--')) continue; // saltar comentarios / líneas vacías
          await pool.query(stmt);
        }
      }

      await pool.query('COMMIT');
      console.log('Transacción COMMIT OK');

      // 4) Stats de pacientes (si existe la columna activo)
      let activos = null;
      let antiguos = null;


      try {
        const activosRes = await pool.query(
          'SELECT COUNT(*)::int AS c FROM paciente WHERE activo = true'
        );
        const antiguosRes = await pool.query(
          'SELECT COUNT(*)::int AS c FROM paciente WHERE activo = false'
        );
        activos = activosRes.rows[0].c;
        antiguos = antiguosRes.rows[0].c;
      } catch (e) {
        console.warn(
          'No se pudieron obtener stats de activos/antiguos (¿columna activo existe?):',
          e.message
        );
      }

      // 5) Respuesta al frontend
      return res.json({
        ok: true,
        mensaje: 'Excel procesado y BD actualizada',
        activos,
        antiguos,
      });
    } catch (err) {
      console.error('Error en /api/cargar-excel-pacientes:', err);
      try {
        await pool.query('ROLLBACK');
      } catch (e) {
        console.error('Error haciendo rollback:', e);
      }
      return res.status(500).json({
        error: 'Error procesando el Excel / ejecutando scripts SQL',
      });
    }
  }
);



// ===========================
// ENDPOINTS DE AUTENTICACIÓN
// ===========================

/**
 * POST /api/auth/login
 * Body: { username, password }
 */
// Reemplaza este código en el endpoint /api/auth/login
app.post('/api/auth/login', async (req, res) => {
  const { username, password } = req.body;

  console.log('=== LOGIN DEBUG ===');
  console.log('Username recibido:', username);
  console.log('Password recibido:', password);

  if (!username || !password) {
    return res.status(400).json({ error: 'Usuario y contraseña son requeridos' });
  }

  try {
    // Buscar usuario con sus permisos
    const sql = `
      SELECT u.*, r.nombre_rol
      FROM usuario u
      JOIN rol r ON u.id_rol = r.id_rol
      WHERE u.username = $1 AND u.activo = true
    `;
    
    const { rows } = await pool.query(sql, [username]);
    console.log('Usuarios encontrados:', rows.length);
    
    if (rows.length === 0) {
      console.log('Usuario no encontrado');
      return res.status(401).json({ error: 'Credenciales inválidas' });
    }

    const usuario = rows[0];
    console.log('Usuario encontrado:', usuario.username);
    console.log('Hash almacenado:', usuario.password_hash);

    // Verificar contraseña
    console.log('Verificando contraseña...');
    const passwordValida = await bcrypt.compare(password, usuario.password_hash);
    console.log('¿Contraseña válida?', passwordValida);
    
    if (!passwordValida) {
      console.log('Contraseña inválida');
      return res.status(401).json({ error: 'Credenciales inválidas' });
    }

    console.log('Login exitoso!');

    // Actualizar último login
    await pool.query(
      'UPDATE usuario SET ultimo_login = current_timestamp WHERE id_usuario = $1',
      [usuario.id_usuario]
    );

    // Obtener sedes del usuario (si es administrativo)
    let sedes = [];
    if (usuario.nombre_rol === 'administrativo_sede') {
      const sedesQuery = `
        SELECT us.codigo_establecimiento, e.nombre_establecimiento
        FROM usuario_sede us
        JOIN establecimiento e ON us.codigo_establecimiento = e.codigo_establecimiento
        WHERE us.id_usuario = $1
      `;
      const sedesResult = await pool.query(sedesQuery, [usuario.id_usuario]);
      sedes = sedesResult.rows;
    }

    // Generar token
    const token = jwt.sign(
      {
        id_usuario: usuario.id_usuario,
        username: usuario.username,
        nombre_completo: usuario.nombre_completo,
        nombre_rol: usuario.nombre_rol,
        id_rol: usuario.id_rol
      },
      JWT_SECRET,
      { expiresIn: JWT_EXPIRES_IN }
    );

    console.log('Token generado:', token);

    res.json({
      token,
      usuario: {
        id_usuario: usuario.id_usuario,
        username: usuario.username,
        nombre_completo: usuario.nombre_completo,
        nombre_rol: usuario.nombre_rol,
        sedes
      }
    });

  } catch (error) {
    console.error('Error en login:', error);
    res.status(500).json({ error: 'Error en el servidor' });
  }
});

/**
 * POST /api/auth/register
 * Body: { username, email, password, nombre_completo, id_rol, sedes? }
 */
app.post('/api/auth/register', verificarToken, esAdministrador, async (req, res) => {
  const { username, email, password, nombre_completo, id_rol, sedes } = req.body;

  if (!username || !email || !password || !nombre_completo || !id_rol) {
    return res.status(400).json({ error: 'Todos los campos son requeridos' });
  }

  try {
    // Validar contraseña
    const sqlValidar = 'SELECT validar_contrasena($1) as valida';
    const { rows } = await pool.query(sqlValidar, [password]);
    
    if (!rows[0].valida) {
      return res.status(400).json({ 
        error: 'La contraseña debe tener al menos 8 caracteres y contener letras y números' 
      });
    }

    // Verificar si el usuario o email ya existen
    const checkSql = 'SELECT id_usuario FROM usuario WHERE username = $1 OR email = $2';
    const checkResult = await pool.query(checkSql, [username, email]);
    
    if (checkResult.rows.length > 0) {
      return res.status(400).json({ error: 'El usuario o email ya están registrados' });
    }

    // Encriptar contraseña
    const passwordHash = await bcrypt.hash(password, 10);

    // Insertar usuario
    const insertSql = `
      INSERT INTO usuario (username, email, password_hash, nombre_completo, id_rol)
      VALUES ($1, $2, $3, $4, $5)
      RETURNING id_usuario, username, email, nombre_completo, id_rol
    `;

    const { rows: newUsuario } = await pool.query(insertSql, [
      username, email, passwordHash, nombre_completo, id_rol
    ]);

    const usuarioCreado = newUsuario[0];

    // Si es administrativo de sede, asignar sedes
    if (id_rol == 2 && sedes && sedes.length > 0) {
      for (const sede of sedes) {
        await pool.query(
          'INSERT INTO usuario_sede (id_usuario, codigo_establecimiento) VALUES ($1, $2)',
          [usuarioCreado.id_usuario, sede]
        );
      }
    }

    res.status(201).json({
      mensaje: 'Usuario creado exitosamente',
      usuario: usuarioCreado
    });

  } catch (error) {
    console.error('Error en registro:', error);
    res.status(500).json({ error: 'Error en el servidor' });
  }
});

/**
 * GET /api/auth/verify
 * Verifica token y devuelve información del usuario
 */
app.get('/api/auth/verify', verificarToken, async (req, res) => {
  try {
    // Obtener información actualizada del usuario
    const sql = `
      SELECT u.id_usuario, u.username, u.nombre_completo, r.nombre_rol
      FROM usuario u
      JOIN rol r ON u.id_rol = r.id_rol
      WHERE u.id_usuario = $1 AND u.activo = true
    `;
    
    const { rows } = await pool.query(sql, [req.usuario.id_usuario]);
    
    if (rows.length === 0) {
      return res.status(401).json({ error: 'Usuario no encontrado' });
    }

    // Obtener sedes si es administrativo
    let sedes = [];
    if (rows[0].nombre_rol === 'administrativo_sede') {
      const sedesQuery = `
        SELECT us.codigo_establecimiento, e.nombre_establecimiento
        FROM usuario_sede us
        JOIN establecimiento e ON us.codigo_establecimiento = e.codigo_establecimiento
        WHERE us.id_usuario = $1
      `;
      const sedesResult = await pool.query(sedesQuery, [req.usuario.id_usuario]);
      sedes = sedesResult.rows;
    }

    res.json({
      usuario: {
        ...rows[0],
        sedes
      }
    });

  } catch (error) {
    console.error('Error en verify:', error);
    res.status(500).json({ error: 'Error en el servidor' });
  }
});

/**
 * GET /api/usuarios
 * Lista todos los usuarios (solo administrador)
 */
app.get('/api/usuarios', verificarToken, esAdministrador, async (req, res) => {
  try {
    const sql = `
      SELECT u.id_usuario, u.username, u.email, u.nombre_completo, u.activo,
             u.fecha_creacion, u.ultimo_login, r.nombre_rol
      FROM usuario u
      JOIN rol r ON u.id_rol = r.id_rol
      ORDER BY u.fecha_creacion DESC
    `;
    
    const { rows } = await pool.query(sql);
    res.json(rows);

  } catch (error) {
    console.error('Error listando usuarios:', error);
    res.status(500).json({ error: 'Error en el servidor' });
  }
});

/**
 * PATCH /api/usuarios/:id/estado
 * Body: { activo: true | false }
 * Solo administrador
 */
app.patch('/api/usuarios/:id/estado', verificarToken, esAdministrador, async (req, res) => {
  const id = req.params.id;
  const { activo } = req.body;

  if (typeof activo !== 'boolean') {
    return res.status(400).json({ error: 'El campo "activo" debe ser boolean' });
  }

  try {
    const sql = `
      UPDATE usuario
      SET activo = $1
      WHERE id_usuario = $2
      RETURNING id_usuario, username, email, nombre_completo, activo
    `;
    const { rows } = await pool.query(sql, [activo, id]);

    if (rows.length === 0) {
      return res.status(404).json({ error: 'Usuario no encontrado' });
    }

    res.json({
      mensaje: activo ? 'Usuario activado' : 'Usuario desactivado',
      usuario: rows[0]
    });
  } catch (error) {
    console.error('Error actualizando estado de usuario:', error);
    res.status(500).json({ error: 'Error en el servidor' });
  }
});


/**
 * GET /api/roles
 * Lista los roles disponibles (solo administrador)
 */
app.get('/api/roles', verificarToken, esAdministrador, async (req, res) => {
  try {
    const sql = `
      SELECT id_rol, nombre_rol, descripcion
      FROM rol
      ORDER BY id_rol
    `;
    const { rows } = await pool.query(sql);
    res.json(rows);
  } catch (error) {
    console.error('Error listando roles:', error);
    res.status(500).json({ error: 'Error en el servidor' });
  }
});


/**
 * GET /api/autorizaciones-por-fecha
 * Query params: fecha_inicio, fecha_fin
 * Solo para administradores
 */
app.get('/api/autorizaciones-por-fecha', verificarToken, esAdministrador, async (req, res) => {
  const { fecha_inicio, fecha_fin } = req.query;

  if (!fecha_inicio || !fecha_fin) {
    return res.status(400).json({ error: 'fecha_inicio y fecha_fin son requeridos' });
  }

  try {
    const sql = `
      SELECT 
        a.numero_autorizacion,
        a.fecha_autorizacion,
        a.observacion,
        p.interno,
        p.primer_nombre || ' ' || COALESCE(p.segundo_nombre, '') || ' ' || 
        p.primer_apellido || ' ' || COALESCE(p.segundo_apellido, '') AS nombre_paciente,
        ips.nombre_ips,
        ips.municipio,
        ips.departamento,
        aut.nombre AS nombre_autorizante,
        e.nombre_establecimiento
      FROM autorizacion a
      JOIN paciente p ON a.interno = p.interno
      JOIN ips ON a.id_ips = ips.id_ips
      JOIN autorizante aut ON a.numero_documento_autorizante = aut.numero_documento
      JOIN ingreso i ON a.interno = i.interno
      JOIN establecimiento e ON i.codigo_establecimiento = e.codigo_establecimiento
      WHERE a.fecha_autorizacion BETWEEN $1 AND $2
      ORDER BY a.fecha_autorizacion DESC, a.numero_autorizacion DESC
    `;

    const { rows } = await pool.query(sql, [fecha_inicio, fecha_fin]);
    res.json(rows);

  } catch (error) {
    console.error('Error en autorizaciones por fecha:', error);
    res.status(500).json({ error: 'Error en el servidor' });
  }
});

app.listen(PORT, () => {
  console.log(`API escuchando en http://localhost:${PORT}`);
});