/**
 * User management routes (admin-only when AUTH_ENABLED=true)
 *
 * GET    /api/v1/users       — list all users
 * POST   /api/v1/users       — create user
 * GET    /api/v1/users/:id   — get user
 * PATCH  /api/v1/users/:id   — update user (display_name, role, password)
 * DELETE /api/v1/users/:id   — delete user
 */
import express from 'express';
import bcrypt  from 'bcrypt';
import pool    from '../db/pool.js';
import { requireAuth, requireAdmin } from '../middleware/auth.js';

const router = express.Router();
router.use(requireAuth, requireAdmin);

const VALID_ROLES = ['admin', 'editor', 'viewer'];

// ── List ──────────────────────────────────────────────────────
router.get('/', async (_req, res, next) => {
  try {
    const { rows } = await pool.query(
      `SELECT u.id, u.username, u.display_name, u.role, u.created_at,
              COUNT(ug.group_id)::int AS group_count
       FROM users u
       LEFT JOIN user_groups ug ON ug.user_id = u.id
       GROUP BY u.id
       ORDER BY u.created_at`
    );
    res.json(rows);
  } catch (err) { next(err); }
});

// ── Create ────────────────────────────────────────────────────
router.post('/', async (req, res, next) => {
  try {
    const { username, password, display_name, role = 'editor' } = req.body;
    if (!username || !password)
      return res.status(400).json({ error: 'username and password required' });
    if (password.length < 8)
      return res.status(400).json({ error: 'Password must be ≥ 8 characters' });
    if (!VALID_ROLES.includes(role))
      return res.status(400).json({ error: `role must be one of: ${VALID_ROLES.join(', ')}` });

    const hash = await bcrypt.hash(password, 12);
    const { rows } = await pool.query(
      `INSERT INTO users (username, password_hash, display_name, role)
       VALUES ($1, $2, $3, $4)
       RETURNING id, username, display_name, role, created_at`,
      [username.trim().toLowerCase(), hash, display_name || username, role]
    );
    res.status(201).json(rows[0]);
  } catch (err) {
    if (err.code === '23505') return res.status(409).json({ error: 'Username already exists' });
    next(err);
  }
});

// ── Get ───────────────────────────────────────────────────────
router.get('/:id', async (req, res, next) => {
  try {
    const { rows } = await pool.query(
      `SELECT id, username, display_name, role, created_at FROM users WHERE id = $1`,
      [req.params.id]
    );
    if (!rows.length) return res.status(404).json({ error: 'User not found' });
    res.json(rows[0]);
  } catch (err) { next(err); }
});

// ── Update ────────────────────────────────────────────────────
router.patch('/:id', async (req, res, next) => {
  try {
    const { display_name, role, password } = req.body;
    const sets = []; const vals = [];

    if (display_name !== undefined) {
      sets.push(`display_name = $${sets.length + 1}`);
      vals.push(display_name);
    }
    if (role !== undefined) {
      if (!VALID_ROLES.includes(role))
        return res.status(400).json({ error: `role must be one of: ${VALID_ROLES.join(', ')}` });
      sets.push(`role = $${sets.length + 1}`);
      vals.push(role);
    }
    if (password) {
      if (password.length < 8)
        return res.status(400).json({ error: 'Password must be ≥ 8 characters' });
      const hashed = await bcrypt.hash(password, 12);
      sets.push(`password_hash = $${sets.length + 1}`);
      vals.push(hashed);
    }
    if (!sets.length) return res.status(400).json({ error: 'Nothing to update' });

    vals.push(req.params.id);
    const { rows } = await pool.query(
      `UPDATE users SET ${sets.join(', ')} WHERE id = $${vals.length}
       RETURNING id, username, display_name, role, created_at`,
      vals
    );
    if (!rows.length) return res.status(404).json({ error: 'User not found' });
    res.json(rows[0]);
  } catch (err) { next(err); }
});

// ── Delete ────────────────────────────────────────────────────
router.delete('/:id', async (req, res, next) => {
  try {
    const { rowCount } = await pool.query('DELETE FROM users WHERE id = $1', [req.params.id]);
    if (!rowCount) return res.status(404).json({ error: 'User not found' });
    res.json({ message: 'User deleted' });
  } catch (err) { next(err); }
});

export default router;
