/**
 * Authentication routes
 *
 * POST /api/v1/auth/login   — exchange username+password for a session cookie
 * POST /api/v1/auth/logout  — destroy the current session
 * GET  /api/v1/auth/me      — return the currently authenticated user
 * POST /api/v1/auth/setup   — one-time admin bootstrap (disabled after first user exists)
 */
import express from 'express';
import bcrypt from 'bcrypt';
import pool from '../db/pool.js';

const router = express.Router();

// ---------------------------------------------------------------------------
// POST /login
// ---------------------------------------------------------------------------
router.post('/login', async (req, res, next) => {
  try {
    const { username, password } = req.body;

    if (!username || !password) {
      return res.status(400).json({ error: 'Username and password are required' });
    }

    const result = await pool.query(
      'SELECT * FROM users WHERE username = $1',
      [username.trim().toLowerCase()]
    );

    if (result.rows.length === 0) {
      // Timing-safe: still run compare on a dummy hash so response time is constant
      await bcrypt.compare(password, '$2b$12$invalidhashpadding000000000000000000000000000000000000');
      return res.status(401).json({ error: 'Invalid credentials' });
    }

    const user = result.rows[0];
    const valid = await bcrypt.compare(password, user.password_hash);

    if (!valid) {
      return res.status(401).json({ error: 'Invalid credentials' });
    }

    // Regenerate session ID to prevent fixation attacks
    req.session.regenerate((err) => {
      if (err) return next(err);
      req.session.userId   = user.id;
      req.session.username = user.username;
      req.session.role     = user.role;
      res.json({
        id:           user.id,
        username:     user.username,
        display_name: user.display_name,
        role:         user.role,
      });
    });
  } catch (err) {
    next(err);
  }
});

// ---------------------------------------------------------------------------
// POST /logout
// ---------------------------------------------------------------------------
router.post('/logout', (req, res, next) => {
  req.session.destroy((err) => {
    if (err) return next(err);
    res.clearCookie('connect.sid');
    res.json({ message: 'Logged out' });
  });
});

// ---------------------------------------------------------------------------
// GET /me
// ---------------------------------------------------------------------------
router.get('/me', async (req, res) => {
  // When auth is disabled return a synthetic user so the frontend auth-guard
  // never receives a 401. Prefer LOCAL_OPERATOR (explicit) or the OS user
  // running the server over a generic "Admin" — that label is misleading
  // because it implies an actual admin account is signed in.
  if (process.env.AUTH_ENABLED !== 'true') {
    const osUser = process.env.LOCAL_OPERATOR
      || process.env.USER
      || process.env.USERNAME
      || 'operator';
    return res.json({
      id: null,
      username: osUser.toLowerCase().replace(/[^a-z0-9._-]/g, ''),
      display_name: osUser,
      role: 'admin',
      synthetic: true,
    });
  }

  if (!req.session || !req.session.userId) {
    return res.status(401).json({ error: 'Not authenticated' });
  }
  try {
    const result = await pool.query(
      'SELECT id, username, display_name, role FROM users WHERE id = $1',
      [req.session.userId]
    );
    if (result.rows.length === 0) {
      req.session.destroy(() => {});
      return res.status(401).json({ error: 'User not found' });
    }
    res.json(result.rows[0]);
  } catch (err) {
    // Fallback to session data if DB unreachable
    res.json({
      id:       req.session.userId,
      username: req.session.username,
      role:     req.session.role,
    });
  }
});

// ---------------------------------------------------------------------------
// POST /setup  — one-time first-admin bootstrap
// ---------------------------------------------------------------------------
router.post('/setup', async (req, res, next) => {
  try {
    const { username, password, display_name } = req.body;

    if (!username || !password) {
      return res.status(400).json({ error: 'Username and password are required' });
    }
    if (password.length < 8) {
      return res.status(400).json({ error: 'Password must be at least 8 characters' });
    }

    // Block if any user already exists
    const count = await pool.query('SELECT COUNT(*) FROM users');
    if (parseInt(count.rows[0].count, 10) > 0) {
      return res.status(403).json({
        error: 'Setup is already complete. Use an existing admin account to add more users.',
      });
    }

    const hash = await bcrypt.hash(password, 12);
    const result = await pool.query(
      `INSERT INTO users (username, password_hash, display_name, role)
       VALUES ($1, $2, $3, 'admin')
       RETURNING id, username, display_name, role`,
      [username.trim().toLowerCase(), hash, display_name || username]
    );

    res.status(201).json(result.rows[0]);
  } catch (err) {
    next(err);
  }
});

export default router;
