import { Router } from 'express';
import { pool } from '../db/pool.js';
import { requireAuth } from '../auth/middleware.js';

const router = Router();
router.use(requireAuth);

function camelToSnake(str: string): string {
  return str.replace(/[A-Z]/g, l => `_${l.toLowerCase()}`);
}

// GET /api/chemicals
router.get('/', async (req, res) => {
  try {
    const result = await pool.query(
      'SELECT *, percentage_full::float AS percentage_full FROM chemicals WHERE user_id = $1 ORDER BY created_at DESC',
      [req.user!.id]
    );
    // Map snake_case columns back to camelCase for the frontend
    const rows = result.rows.map(snakeToCamel);
    res.json(rows);
  } catch (err) {
    console.error(err);
    res.status(500).json({ error: 'Internal server error' });
  }
});

// POST /api/chemicals
router.post('/', async (req, res) => {
  try {
    const b = req.body;
    const result = await pool.query(`
      INSERT INTO chemicals (
        user_id, pi_first_name, physical_state, chemical_name, bldg_code, lab,
        storage_location, storage_device, number_of_containers, amount_per_container,
        unit_of_measure, cas_number,
        chemical_formula, molecular_weight, vendor, catalog_number, lot_number,
        expiration_date, concentration, percentage_full, needs_manual_entry,
        scanned_image, comments, barcode, contact
      ) VALUES (
        $1,$2,$3,$4,$5,$6,$7,$8,$9,$10,$11,$12,
        $13,$14,$15,$16,$17,$18,$19,$20,$21,$22,$23,$24,$25
      ) RETURNING *, percentage_full::float AS percentage_full, expiration_date::text AS expiration_date`,
      [
        req.user!.id, b.piFirstName, b.physicalState, b.chemicalName, b.bldgCode, b.lab,
        b.storageLocation, b.storageDevice, b.numberOfContainers, b.amountPerContainer,
        b.unitOfMeasure, b.casNumber,
        b.chemicalFormula || null, b.molecularWeight || null, b.vendor || null,
        b.catalogNumber || null, b.lotNumber || null,
        b.expirationDate || null, b.concentration || null,
        b.percentageFull ?? null, b.needsManualEntry ?? null,
        b.scannedImage || null, b.comments || null, b.barcode || null, b.contact || null,
      ]
    );
    res.status(201).json(snakeToCamel(result.rows[0]));
  } catch (err) {
    console.error(err);
    res.status(500).json({ error: 'Internal server error' });
  }
});

// PATCH /api/chemicals/:id
router.patch('/:id', async (req, res) => {
  try {
    const skip = new Set(['id', 'user_id', 'created_at', 'updated_at']);
    const fields = Object.keys(req.body).filter(k => !skip.has(k) && !skip.has(camelToSnake(k)));
    if (fields.length === 0) return res.status(400).json({ error: 'No fields to update' });

    const snakeFields = fields.map(camelToSnake);
    const setClauses = snakeFields.map((f, i) => `${f} = $${i + 3}`).join(', ');
    const values = fields.map(f => req.body[f] || null);

    const result = await pool.query(
      `UPDATE chemicals SET ${setClauses}, updated_at = NOW()
      WHERE id = $1 AND user_id = $2
      RETURNING *, percentage_full::float AS percentage_full, expiration_date::text AS expiration_date`,
      [req.params.id, req.user!.id, ...values]
    );
    if (result.rows.length === 0) return res.status(404).json({ error: 'Not found' });
    res.json(snakeToCamel(result.rows[0]));
  } catch (err) {
    console.error(err);
    res.status(500).json({ error: 'Internal server error' });
  }
});

// POST /api/chemicals/import
router.post('/import', async (req, res) => {
  const rows: Partial<Record<string, unknown>>[] = req.body.rows;
  if (!Array.isArray(rows) || rows.length === 0) {
    return res.status(400).json({ error: 'No rows provided' });
  }
  if (rows.length > 1000) {
    return res.status(400).json({ error: 'Maximum 1000 rows per import' });
  }

  const skipFields = new Set(['id', 'userId', 'createdAt', 'updatedAt', 'dateEntered', 'lastChanged']);
  let imported = 0;
  const errors: string[] = [];

  for (let i = 0; i < rows.length; i++) {
    const b = rows[i];
    const fields = Object.keys(b).filter(k => !skipFields.has(k) && b[k] !== '' && b[k] != null);
    if (fields.length === 0) continue;

    const snakeCols = fields.map(camelToSnake);
    const allCols = ['user_id', ...snakeCols];
    const placeholders = allCols.map((_, idx) => `$${idx + 1}`).join(', ');
    const values = [req.user!.id, ...fields.map(f => b[f] || null)];

    try {
      await pool.query(
        `INSERT INTO chemicals (${allCols.join(', ')}) VALUES (${placeholders})`,
        values
      );
      imported++;
    } catch (err) {
      errors.push(`Row ${i + 1}: ${(err as Error).message}`);
    }
  }

  res.json({ imported, errors });
});

// DELETE /api/chemicals/:id
router.delete('/:id', async (req, res) => {
  try {
    await pool.query('DELETE FROM chemicals WHERE id = $1 AND user_id = $2',
      [req.params.id, req.user!.id]);
    res.status(204).end();
  } catch (err) {
    console.error(err);
    res.status(500).json({ error: 'Internal server error' });
  }
});

function snakeToCamel(row: Record<string, unknown>): Record<string, unknown> {
  return Object.fromEntries(
    Object.entries(row).map(([k, v]) => [
      k.replace(/_([a-z])/g, (_, l) => l.toUpperCase()),
      v,
    ])
  );
}

export default router;
