/**
 * Authentication middleware.
 *
 * When AUTH_ENABLED=true in the environment, every protected route requires
 * either:
 *   - An active session (set by POST /api/v1/auth/login), or
 *   - A valid Bearer token in Authorization header (set by POST /api/v1/tokens)
 *
 * When AUTH_ENABLED is unset or any other value, all middleware is a no-op so
 * the stack can be run without user accounts during development.
 */
import crypto from 'crypto';
import pool   from '../db/pool.js';

export const requireAuth = async (req, res, next) => {
  if (process.env.AUTH_ENABLED !== 'true') return next();

  // ── Session-based auth ────────────────────────────────────────
  if (req.session?.userId) {
    req.user = {
      id:       req.session.userId,
      username: req.session.username,
      role:     req.session.role,
    };
    return next();
  }

  // ── Bearer token auth ─────────────────────────────────────────
  const authHeader = req.headers.authorization;
  if (authHeader?.startsWith('Bearer ')) {
    const raw  = authHeader.slice(7).trim();
    const hash = crypto.createHash('sha256').update(raw).digest('hex');
    try {
      const { rows } = await pool.query(
        `SELECT t.user_id AS id, u.username, u.role
         FROM api_tokens t
         JOIN users u ON u.id = t.user_id
         WHERE t.token_hash = $1
           AND (t.expires_at IS NULL OR t.expires_at > NOW())`,
        [hash]
      );
      if (rows.length > 0) {
        req.user = rows[0];
        // Fire-and-forget last_used_at update
        pool.query(
          'UPDATE api_tokens SET last_used_at = NOW() WHERE token_hash = $1',
          [hash]
        ).catch(() => {});
        return next();
      }
    } catch (err) {
      return next(err);
    }
  }

  return res.status(401).json({ error: 'Unauthorized' });
};

export const requireAdmin = (req, res, next) => {
  if (process.env.AUTH_ENABLED !== 'true') return next();
  if (req.user?.role === 'admin') return next();
  return res.status(403).json({ error: 'Admin access required' });
};
