// services/app/src/routes.legacy.js
// -----------------------------------------------------------------------------
// Endpoints legacy de SuiteCoffee extraídos del index original y montados
// como módulo. No elimina nada; sólo organiza y robustece.
//
// Cómo se usa: el nuevo services/app/src/index.js hace
//   const legacy = await import('./routes.legacy.js')
//   legacy.default(app, { requireAuth, withTenant, done, mainPool, tenantsPool, express })
// -----------------------------------------------------------------------------

export default function mount(app, ctx) {
  const { requireAuth, withTenant, done, mainPool, tenantsPool, express } = ctx;

  // Aliases de compatibilidad con el archivo original
  const pool = mainPool; // el original usaba `pool` (DB principal)

  // ---------------------------------------------------------------------------
  // Helpers y seguridad (copiados/adaptados del archivo original)
  // ---------------------------------------------------------------------------
  const ALLOWED_TABLES = [
    'roles','usuarios','usua_roles',
    'categorias','productos',
    'clientes','mesas',
    'comandas','deta_comandas',
    'proveedores','compras','deta_comp_producto',
    'mate_primas','deta_comp_materias',
    'prov_producto','prov_mate_prima',
    'receta_producto', 'asistencia_resumen_diario',
    'asistencia_intervalo', 'vw_compras'
  ];
  const VALID_IDENT = /^[a-zA-Z_][a-zA-Z0-9_]*$/;
  const q = (s) => `"${String(s).replace(/"/g, '""')}"`; // quote ident simple
  function ensureTable(name) {
    const t = String(name || '').toLowerCase();
    if (!ALLOWED_TABLES.includes(t)) throw new Error('Tabla no permitida');
    return t;
  }

  async function getClient() { // el original devolvía pool.connect()
    const client = await pool.connect();
    return client;
  }

  // Columnas de una tabla
  async function loadColumns(client, table) {
    const sql = `
      SELECT
        c.column_name,
        c.data_type,
        c.is_nullable = 'YES' AS is_nullable,
        c.column_default,
        EXISTS (
          SELECT 1 FROM pg_attribute a
          JOIN pg_class t ON t.oid = a.attrelid
          JOIN pg_index i ON i.indrelid = t.oid AND a.attnum = ANY(i.indkey)
          WHERE t.relname = $1 AND i.indisprimary AND a.attname = c.column_name
        ) AS is_primary,
        (
          SELECT a.attgenerated = 's' OR a.attidentity IN ('a','d')
          FROM pg_attribute a
          JOIN pg_class t2 ON t2.oid = a.attrelid
          WHERE t2.relname = $1 AND a.attname = c.column_name
        ) AS is_generated
      FROM information_schema.columns c
      WHERE c.table_schema = 'public' AND c.table_name = $1
      ORDER BY c.ordinal_position`;
    const { rows } = await client.query(sql, [table]);
    return rows;
  }

  // PKs de una tabla
  async function loadPrimaryKey(client, table) {
    const sql = `
      SELECT a.attname AS column_name
      FROM pg_index i
      JOIN pg_attribute a ON a.attrelid = i.indrelid AND a.attnum = ANY(i.indkey)
      JOIN pg_class t ON t.oid = i.indrelid
      WHERE t.relname = $1 AND i.indisprimary`;
    const { rows } = await client.query(sql, [table]);
    return rows.map(r => r.column_name);
  }

  // FKs salientes de una tabla → { [column]: { foreign_table, foreign_column } }
  async function loadForeignKeys(client, table) {
    const sql = `
      SELECT
        kcu.column_name AS column_name,
        ccu.table_name  AS foreign_table,
        ccu.column_name AS foreign_column
      FROM information_schema.table_constraints tc
      JOIN information_schema.key_column_usage kcu
        ON tc.constraint_name = kcu.constraint_name
       AND tc.table_schema = kcu.table_schema
      JOIN information_schema.constraint_column_usage ccu
        ON ccu.constraint_name = tc.constraint_name
       AND ccu.table_schema = tc.table_schema
      WHERE tc.constraint_type = 'FOREIGN KEY'
        AND tc.table_schema = 'public'
        AND tc.table_name = $1`;
    const { rows } = await client.query(sql, [table]);
    const map = {};
    for (const r of rows) map[r.column_name] = { foreign_table: r.foreign_table, foreign_column: r.foreign_column };
    return map;
  }

  // Heurística para elegir una columna "label" en tablas referenciadas
  async function pickLabelColumn(client, refTable) {
    const preferred = ['nombre','raz_social','apodo','documento','correo','telefono','descripcion','detalle'];
    const { rows } = await client.query(
      `SELECT column_name, data_type
         FROM information_schema.columns
        WHERE table_schema='public' AND table_name=$1
        ORDER BY ordinal_position`, [refTable]
    );
    for (const cand of preferred) if (rows.find(r => r.column_name === cand)) return cand;
    const textish = rows.find(r => /text|character varying|varchar/i.test(r.data_type));
    if (textish) return textish.column_name;
    return rows[0]?.column_name || 'id';
  }

  // ---------------------------------------------------------------------------
  // RUTAS DE UI (vistas)
  // ---------------------------------------------------------------------------
  app.get('/', (req, res) => {
    res.locals.pageTitle = 'Dashboard';
    res.locals.pageId = 'home';
    res.render('dashboard');
  });

  app.get('/dashboard', (req, res) => {
    res.locals.pageTitle = 'Dashboard';
    res.locals.pageId = 'dashboard';
    res.render('dashboard');
  });

  app.get('/comandas', (req, res) => {
    res.locals.pageTitle = 'Comandas';
    res.locals.pageId = 'comandas';
    res.render('comandas');
  });

  app.get('/estadoComandas', (req, res) => {
    res.locals.pageTitle = 'Estado de Comandas';
    res.locals.pageId = 'estadoComandas';
    res.render('estadoComandas');
  });

  app.get('/productos', (req, res) => {
    res.locals.pageTitle = 'Productos';
    res.locals.pageId = 'productos';
    res.render('productos');
  });

  app.get('/usuarios', (req, res) => {
    res.locals.pageTitle = 'Usuarios';
    res.locals.pageId = 'usuarios';
    res.render('usuarios');
  });

  app.get('/reportes', (req, res) => {
    res.locals.pageTitle = 'Reportes';
    res.locals.pageId = 'reportes';
    res.render('reportes');
  });

  app.get('/compras', (req, res) => {
    res.locals.pageTitle = 'Compras';
    res.locals.pageId = 'compras';
    res.render('compras');
  });

  // ---------------------------------------------------------------------------
  // API: ejemplos por-tenant y utilitarios (introspección)
  // ---------------------------------------------------------------------------
  // Ejemplo conservado del original (usar search_path via withTenant)
  app.get('/api/productos', requireAuth, withTenant, async (req, res, next) => {
    const { rows } = await req.pg.query('SELECT * FROM productos ORDER BY id');
    res.json(rows);
  }, done);

  // Listado de tablas permitidas
  app.get('/api/tables', async (_req, res) => {
    res.json(ALLOWED_TABLES);
  });

  // Esquema de una tabla (columnas + FKs)
  app.get('/api/schema/:table', async (req, res) => {
    try {
      const table = ensureTable(req.params.table);
      const client = await getClient();
      try {
        const columns = await loadColumns(client, table);
        const fks = await loadForeignKeys(client, table);
        const enriched = columns.map(c => ({ ...c, foreign: fks[c.column_name] || null }));
        res.json({ table, columns: enriched });
      } finally { client.release(); }
    } catch (e) {
      res.status(400).json({ error: e.message });
    }
  });

  // Opciones para una columna con FK (id/label)
  app.get('/api/options/:table/:column', async (req, res) => {
    try {
      const table = ensureTable(req.params.table);
      const column = req.params.column;
      if (!VALID_IDENT.test(column)) throw new Error('Columna inválida');

      const client = await getClient();
      try {
        const fks = await loadForeignKeys(client, table);
        const fk = fks[column];
        if (!fk) return res.json([]);
        const refTable = fk.foreign_table;
        const refId = fk.foreign_column;
        const labelCol = await pickLabelColumn(client, refTable);
        const sql = `SELECT ${q(refId)} AS id, ${q(labelCol)} AS label FROM ${q(refTable)} ORDER BY ${q(labelCol)} LIMIT 1000`;
        const result = await client.query(sql);
        res.json(result.rows);
      } finally { client.release(); }
    } catch (e) {
      res.status(400).json({ error: e.message });
    }
  });

  // Datos de una tabla (limitados) — vista rápida
  app.get('/api/table/:table', async (req, res) => {
    try {
      const table = ensureTable(req.params.table);
      const limit = Math.min(parseInt(req.query.limit || '100', 10), 1000);
      const client = await getClient();
      try {
        const pks = await loadPrimaryKey(client, table);
        const order = pks[0] ? q(pks[0]) : '1';
        const sql = `SELECT * FROM ${q(table)} ORDER BY ${order} LIMIT $1`;
        const { rows } = await client.query(sql, [limit]);
        res.json(rows);
      } finally { client.release(); }
    } catch (e) {
      res.status(400).json({ error: e.message, code: e.code, detail: e.detail });
    }
  });

  // Crear/actualizar registros genéricos (placeholder: pega aquí tu lógica original)
  app.post('/api/table/:table', async (req, res) => {
    // TODO: Pegar implementación original (insert/update genérico) aquí.
    // Sugerencia: validar payload contra loadColumns(client, table),
    // construir INSERT/UPDATE dinámico ignorando columnas generadas y PKs cuando corresponda.
    res.status(501).json({ error: 'not-implemented', detail: 'Pegar lógica original de POST /api/table/:table' });
  });

  // ---------------------------------------------------------------------------
  // Endpoints de negocio (conservados tal cual cuando fue posible)
  // ---------------------------------------------------------------------------

  // Detalle de una comanda
  app.get('/api/comandas/:id/detalle', (req, res, next) =>
    pool.query(
      `SELECT id_det_comanda, id_producto, producto_nombre,
              cantidad, pre_unitario, subtotal, observaciones
         FROM public.v_comandas_detalle_items
        WHERE id_comanda = $1::int
        ORDER BY id_det_comanda`,
      [req.params.id]
    )
    .then(r => res.json(r.rows))
    .catch(next)
  );

  // ---------------------------------------------------------------------------
  // RPC / Reportes / Procedimientos (stubs con TODO si no se extrajo el SQL)
  // ---------------------------------------------------------------------------
  app.post('/api/rpc/find_usuarios_por_documentos', async (req, res) => {
    // TODO: Pegar el SQL original. Ejemplo:
    // const { documentos } = req.body || {};
    // const { rows } = await pool.query('SELECT * FROM public.find_usuarios_por_documentos($1::jsonb)', [JSON.stringify(documentos||[])])
    // res.json(rows);
    res.status(501).json({ error: 'not-implemented' });
  });

  app.post('/api/rpc/import_asistencia', async (req, res) => {
    // TODO: pegar lógica original
    res.status(501).json({ error: 'not-implemented' });
  });

  app.post('/api/rpc/asistencia_get', async (req, res) => {
    // TODO
    res.status(501).json({ error: 'not-implemented' });
  });

  app.post('/api/rpc/asistencia_update_raw', async (req, res) => {
    // TODO
    res.status(501).json({ error: 'not-implemented' });
  });

  app.post('/api/rpc/asistencia_delete_raw', async (req, res) => {
    // TODO
    res.status(501).json({ error: 'not-implemented' });
  });

  app.post('/api/rpc/report_tickets', async (req, res) => {
    // TODO: posiblemente public.report_tickets_year(year int)
    res.status(501).json({ error: 'not-implemented' });
  });

  app.post('/api/rpc/report_asistencia', async (req, res) => {
    // TODO: posiblemente public.report_asistencia(desde date, hasta date)
    res.status(501).json({ error: 'not-implemented' });
  });

  app.get('/api/rpc/report_gastos', async (req, res) => {
    // TODO: pegar la SELECT/función original
    res.status(501).json({ error: 'not-implemented' });
  });

  app.post('/api/rpc/report_gastos', async (req, res) => {
    try {
      // Ejemplo de carcasa robusta en base a nombres vistos
      const { desde, hasta } = req.body || {};
      if (!desde || !hasta) return res.status(400).json({ error: 'desde y hasta son requeridos' });
      // TODO: reemplazar por tu SQL real; esto es un placeholder ilutrativo
      const sql = 'SELECT * FROM public.report_gastos($1::date, $2::date)';
      try {
        const { rows } = await pool.query(sql, [desde, hasta]);
        res.json(rows);
      } catch (e) {
        res.status(500).json({ error: 'report_gastos failed', message: e.message, detail: e.detail, code: e.code });
      }
    } catch (e) {
      res.status(500).json({ error: 'report_gastos failed', message: e.message });
    }
  });

  app.post('/api/rpc/save_compra', async (req, res) => { res.status(501).json({ error: 'not-implemented' }); });
  app.post('/api/rpc/get_compra', async (req, res) => { res.status(501).json({ error: 'not-implemented' }); });
  app.post('/api/rpc/delete_compra', async (req, res) => { res.status(501).json({ error: 'not-implemented' }); });
}
