// app/src/index.js
import chalk from 'chalk'; // Colores!
import express from 'express';
import expressLayouts from 'express-ejs-layouts';
import cors from 'cors';
import { Pool } from 'pg';

// Rutas
import path from 'path';
import { fileURLToPath } from 'url';
const __filename = fileURLToPath(import.meta.url);
const __dirname = path.dirname(__filename);

// Variables de Entorno
import dotenv, { config } from 'dotenv';

// Obtención de la ruta de la variable de entorno correspondiente a NODE_ENV
try {
  if (process.env.NODE_ENV === 'development') {
    dotenv.config({ path: path.resolve(__dirname, '../.env.development' )});
    console.log(`Activando entorno de ->${chalk.green(` DEVELOPMENT `)}`);
  } else if (process.env.NODE_ENV === 'stage') {
    dotenv.config({ path: path.resolve(__dirname, '../.env.test' )});
    console.log(`Activando entorno de ->${chalk.yellow(` TESTING `)}`);
  } else if (process.env.NODE_ENV === 'production') {
    dotenv.config({ path: path.resolve(__dirname, '../.env.production' )});
    console.log(`Activando entorno de ->${chalk.red(` PRODUCTION `)}`);
  }
} catch (error) {
  console.log("A ocurrido un error al seleccionar el entorno. \nError: " + error);
}

// Renderiado
const app = express();
app.use(cors());
app.use(express.json());
app.use(express.static(path.join(__dirname, 'pages')));

// Configuración de conexión PostgreSQL

const dbConfig = {
  host: process.env.DB_HOST,
  user: process.env.DB_USER,
  password: process.env.DB_PASS,
  database: process.env.DB_NAME,
  port: process.env.DB_LOCAL_PORT
};

const pool = new Pool(dbConfig);


async function verificarConexion() {
  try {
    const client = await pool.connect();
    const res = await client.query('SELECT NOW() AS hora');
    console.log(`\nConexión con la base de datos ${chalk.green(process.env.DB_NAME)} fue exitosa.`);
    console.log('Fecha y hora actual de la base de datos:', res.rows[0].hora);
    client.release(); // liberar el cliente de nuevo al pool
  } catch (error) {
    console.error('Error al conectar con la base de datos al iniciar:', error.message);
    console.error(`Troubleshooting:\n1. Compruebe que las bases de datos se iniciaron correctamente.\n2. Verifique las credenciales y puertos de acceso a la base de datos.\n3. Si está conectandose a una base de datos externa a localhost, verifique las reglas del firewal de entrada y salida de ambos dispositivos.`);

  }
}


// === Servir páginas estáticas ===

app.get('/roles',    (req, res) => res.sendFile(path.join(__dirname, 'pages', 'roles.html')));
app.get('/usuarios', (req, res) => res.sendFile(path.join(__dirname, 'pages', 'usuarios.html')));
app.get('/categorias',(req, res) => res.sendFile(path.join(__dirname, 'pages', 'categorias.html')));
app.get('/productos', (req, res) => res.sendFile(path.join(__dirname, 'pages', 'productos.html')));


// Helper de consulta con acquire/release explícito
async function q(text, params) {
  const client = await pool.connect();
  try {
    return await client.query(text, params);
  } finally {
    client.release();
  }
}

// === API Roles ===
  // GET: listar
  app.get('/api/roles', async (req, res) => {
      try {
        const { rows } = await q('SELECT id_rol, nombre FROM roles ORDER BY id_rol ASC');
        res.json(rows);
      } catch (e) {
        console.error(e);
        res.status(500).json({ error: 'No se pudo listar roles' });
      }
  });

  // POST: crear
  app.post('/api/roles', async (req, res) => {
      try {
        const { nombre } = req.body;
        if (!nombre || !nombre.trim()) return res.status(400).json({ error: 'Nombre requerido' });
        const { rows } = await q(
          'INSERT INTO roles (nombre) VALUES ($1) RETURNING id_rol, nombre',
          [nombre.trim()]
        );
        res.status(201).json(rows[0]);
      } catch (e) {
        console.error(e);
        // Manejo de único/duplicado
        if (e.code === '23505') return res.status(409).json({ error: 'El rol ya existe' });
        res.status(500).json({ error: 'No se pudo crear el rol' });
      }
  });

// === API Usuarios ===
  // GET: listar
  app.get('/api/usuarios', async (req, res) => {
    try {
      const { rows } = await q(`
        SELECT id_usuario, documento, img_perfil, nombre, apellido, correo, telefono, fec_nacimiento, activo
        FROM usuarios
        ORDER BY id_usuario ASC
      `);
      res.json(rows);
    } catch (e) {
      console.error(e);
      res.status(500).json({ error: 'No se pudo listar usuarios' });
    }
  });

  // POST: crear
  app.post('/api/usuarios', async (req, res) => {
    try {
      const { documento, nombre, apellido, correo, telefono, fec_nacimiento } = req.body;
      if (!nombre || !apellido) return res.status(400).json({ error: 'Nombre y apellido requeridos' });

      const { rows } = await q(`
        INSERT INTO usuarios (documento, nombre, apellido, correo, telefono, fec_nacimiento)
        VALUES ($1, $2, $3, $4, $5, $6)
        RETURNING id_usuario, documento, nombre, apellido, correo, telefono, fec_nacimiento, activo
      `, [
        documento || null,
        nombre.trim(),
        apellido.trim(),
        correo || null,
        telefono || null,
        fec_nacimiento || null
      ]);

      res.status(201).json(rows[0]);
    } catch (e) {
      console.error(e);
      if (e.code === '23505') return res.status(409).json({ error: 'Documento/Correo/Teléfono ya existe' });
      res.status(500).json({ error: 'No se pudo crear el usuario' });
    }
  });

// === API Categorías ===
  // GET: listar
  app.get('/api/categorias', async (req, res) => {
    try {
      const { rows } = await q('SELECT id_categoria, nombre, visible FROM categorias ORDER BY id_categoria ASC');
      res.json(rows);
    } catch (e) {
      console.error(e);
      res.status(500).json({ error: 'No se pudo listar categorías' });
    }
  });

  // POST: crear
  app.post('/api/categorias', async (req, res) => {
    try {
      const { nombre, visible } = req.body;
      if (!nombre || !nombre.trim()) return res.status(400).json({ error: 'Nombre requerido' });
      const vis = (typeof visible === 'boolean') ? visible : true;

      const { rows } = await q(`
        INSERT INTO categorias (nombre, visible)
        VALUES ($1, $2)
        RETURNING id_categoria, nombre, visible
      `, [nombre.trim(), vis]);

      res.status(201).json(rows[0]);
    } catch (e) {
      console.error(e);
      if (e.code === '23505') return res.status(409).json({ error: 'La categoría ya existe' });
      res.status(500).json({ error: 'No se pudo crear la categoría' });
    }
  });

// === API Productos ===
  // GET: listar
  app.get('/api/productos', async (req, res) => {
    try {
      const { rows } = await q(`
        SELECT id_producto, nombre, img_producto, precio, activo, id_categoria
        FROM productos
        ORDER BY id_producto ASC
      `);
      res.json(rows);
    } catch (e) {
      console.error(e);
      res.status(500).json({ error: 'No se pudo listar productos' });
    }
  });

  // POST: crear
  app.post('/api/productos', async (req, res) => {
    try {
      let { nombre, id_categoria, precio } = req.body;
      if (!nombre || !nombre.trim()) return res.status(400).json({ error: 'Nombre requerido' });
      id_categoria = parseInt(id_categoria, 10);
      precio = parseFloat(precio);
      if (!Number.isInteger(id_categoria)) return res.status(400).json({ error: 'id_categoria inválido' });
      if (!(precio >= 0)) return res.status(400).json({ error: 'precio inválido' });

      const { rows } = await q(`
        INSERT INTO productos (nombre, id_categoria, precio)
        VALUES ($1, $2, $3)
        RETURNING id_producto, nombre, precio, activo, id_categoria
      `, [nombre.trim(), id_categoria, precio]);

      res.status(201).json(rows[0]);
    } catch (e) {
      console.error(e);
      // FK categories / checks
      if (e.code === '23503') return res.status(400).json({ error: 'La categoría no existe' });
      res.status(500).json({ error: 'No se pudo crear el producto' });
    }
  });


// Colores personalizados
let primaryColor = chalk.hex('#'+`${process.env.COL_PRI}`);
let secondaryColor = chalk.hex('#'+`${process.env.COL_SEC}`);
// let backgroundColor = chalk.hex('#'+`${process.env.COL_BG}`);


app.use(expressLayouts);
// Iniciar servidor
app.listen( process.env.PORT, () => {
  console.log(`Servidor de ${chalk.red('aplicación')} de ${secondaryColor('SuiteCoffee')} corriendo en ${chalk.yellow(`http://localhost:${process.env.PORT}\n`)}` );
  console.log(chalk.grey(`Comprobando accesibilidad a la db ${chalk.green(process.env.DB_NAME)} del host ${chalk.white(`${process.env.DB_HOST}`)} ...`));
  verificarConexion();
});

app.get("/health", async (req, res) => {
  // Podés chequear DB aquí. 200 = healthy; 503 = not ready.
  res.status(200).json({ status: "ok" });
});