'use strict';

const express = require('express');
const { pool, withTransaction } = require('../db');
const { requireAdmin } = require('../auth');
const { hashPassword, verifyPassword } = require('../security');
const { USER_CATEGORIES, MENU_KEYS } = require('../constants');
const { normalizeUsername, isValidUsername, isStrongEnoughPassword, asyncHandler } = require('../utils');
const { writeAudit } = require('../audit');

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

function normalizePermissions(value) {
  if (!Array.isArray(value)) return [];
  return [...new Set(value.filter((item) => MENU_KEYS.includes(item)))];
}

router.get('/stats', asyncHandler(async (_req, res) => {
  const [[userCount]] = await pool.query('SELECT COUNT(*) AS count FROM users');
  const [[custodyCount]] = await pool.query('SELECT COUNT(*) AS count FROM custodies');
  const [[latest]] = await pool.query('SELECT custody_date, custody_number, created_at FROM custodies ORDER BY id DESC LIMIT 1');
  res.json({
    users: userCount.count,
    custodies: custodyCount.count,
    latestCustody: latest || null,
  });
}));

router.get('/users', asyncHandler(async (_req, res) => {
  const [rows] = await pool.query(
    `SELECT u.id, u.username, u.category, u.created_at,
            GROUP_CONCAT(up.menu_key ORDER BY up.menu_key SEPARATOR ',') AS permissions
     FROM users u
     LEFT JOIN user_permissions up ON up.user_id = u.id
     GROUP BY u.id
     ORDER BY u.id DESC`,
  );
  res.json({
    users: rows.map((row) => ({
      ...row,
      permissions: row.permissions ? row.permissions.split(',') : [],
    })),
  });
}));

router.post('/users', asyncHandler(async (req, res) => {
  const username = normalizeUsername(req.body?.username);
  const password = String(req.body?.password || '');
  const category = String(req.body?.category || '');
  const permissions = normalizePermissions(req.body?.permissions);

  if (!isValidUsername(username)) return res.status(400).json({ message: 'اسم المستخدم من 3 إلى 80 حرفًا وبدون مسافات.' });
  if (!isStrongEnoughPassword(password)) return res.status(400).json({ message: 'كلمة المرور يجب أن تكون 8 أحرف على الأقل.' });
  if (!USER_CATEGORIES.includes(category)) return res.status(400).json({ message: 'اختر فئة صحيحة.' });
  if (!permissions.length) return res.status(400).json({ message: 'اختر قائمة واحدة على الأقل للمستخدم.' });

  const passwordHash = await hashPassword(password);
  const userId = await withTransaction(async (connection) => {
    const [result] = await connection.execute(
      'INSERT INTO users (username, password_hash, category) VALUES (?, ?, ?)',
      [username, passwordHash, category],
    );
    for (const menuKey of permissions) {
      await connection.execute('INSERT INTO user_permissions (user_id, menu_key) VALUES (?, ?)', [result.insertId, menuKey]);
    }
    return result.insertId;
  });

  await writeAudit({
    req,
    actorType: 'admin',
    actorId: req.admin.id,
    actorName: req.admin.username,
    actionKey: 'user_created',
    entityType: 'user',
    entityId: userId,
    details: { username, category, permissions },
  });
  res.status(201).json({ message: 'تمت إضافة المستخدم.', userId });
}));

router.put('/users/:id', asyncHandler(async (req, res) => {
  const userId = Number.parseInt(req.params.id, 10);
  const username = normalizeUsername(req.body?.username);
  const category = String(req.body?.category || '');
  const permissions = normalizePermissions(req.body?.permissions);

  if (!Number.isInteger(userId) || userId <= 0) return res.status(400).json({ message: 'معرّف المستخدم غير صحيح.' });
  if (!isValidUsername(username)) return res.status(400).json({ message: 'اسم المستخدم غير صحيح.' });
  if (!USER_CATEGORIES.includes(category)) return res.status(400).json({ message: 'اختر فئة صحيحة.' });
  if (!permissions.length) return res.status(400).json({ message: 'اختر قائمة واحدة على الأقل.' });

  await withTransaction(async (connection) => {
    const [result] = await connection.execute('UPDATE users SET username = ?, category = ? WHERE id = ?', [username, category, userId]);
    if (!result.affectedRows) {
      const error = new Error('المستخدم غير موجود.');
      error.statusCode = 404;
      throw error;
    }
    await connection.execute('DELETE FROM user_permissions WHERE user_id = ?', [userId]);
    for (const menuKey of permissions) {
      await connection.execute('INSERT INTO user_permissions (user_id, menu_key) VALUES (?, ?)', [userId, menuKey]);
    }
  });

  await writeAudit({
    req,
    actorType: 'admin',
    actorId: req.admin.id,
    actorName: req.admin.username,
    actionKey: 'user_updated',
    entityType: 'user',
    entityId: userId,
    details: { username, category, permissions },
  });
  res.json({ message: 'تم تحديث المستخدم.' });
}));

router.put('/users/:id/password', asyncHandler(async (req, res) => {
  const userId = Number.parseInt(req.params.id, 10);
  const password = String(req.body?.password || '');
  if (!Number.isInteger(userId) || userId <= 0) return res.status(400).json({ message: 'معرّف المستخدم غير صحيح.' });
  if (!isStrongEnoughPassword(password)) return res.status(400).json({ message: 'كلمة المرور يجب أن تكون 8 أحرف على الأقل.' });

  const passwordHash = await hashPassword(password);
  const [result] = await pool.execute('UPDATE users SET password_hash = ? WHERE id = ?', [passwordHash, userId]);
  if (!result.affectedRows) return res.status(404).json({ message: 'المستخدم غير موجود.' });

  await writeAudit({
    req,
    actorType: 'admin',
    actorId: req.admin.id,
    actorName: req.admin.username,
    actionKey: 'user_password_changed',
    entityType: 'user',
    entityId: userId,
  });
  res.json({ message: 'تم تغيير كلمة المرور. تبقى جلسة المستخدم الحالية متصلة.' });
}));

router.delete('/users/:id', asyncHandler(async (req, res) => {
  const userId = Number.parseInt(req.params.id, 10);
  if (!Number.isInteger(userId) || userId <= 0) return res.status(400).json({ message: 'معرّف المستخدم غير صحيح.' });

  const [rows] = await pool.execute('SELECT username FROM users WHERE id = ? LIMIT 1', [userId]);
  if (!rows.length) return res.status(404).json({ message: 'المستخدم غير موجود.' });

  await pool.execute('DELETE FROM users WHERE id = ?', [userId]);
  await writeAudit({
    req,
    actorType: 'admin',
    actorId: req.admin.id,
    actorName: req.admin.username,
    actionKey: 'user_deleted',
    entityType: 'user',
    entityId: userId,
    details: { username: rows[0].username },
  });
  res.json({ message: 'تم حذف المستخدم وإنهاء جميع جلساته فورًا.' });
}));

router.put('/password', asyncHandler(async (req, res) => {
  const currentPassword = String(req.body?.currentPassword || '');
  const newPassword = String(req.body?.newPassword || '');
  if (!isStrongEnoughPassword(newPassword)) return res.status(400).json({ message: 'كلمة المرور الجديدة يجب أن تكون 8 أحرف على الأقل.' });

  const [rows] = await pool.execute('SELECT password_hash FROM admins WHERE id = ? LIMIT 1', [req.admin.id]);
  if (!rows.length || !(await verifyPassword(currentPassword, rows[0].password_hash))) {
    return res.status(400).json({ message: 'كلمة المرور الحالية غير صحيحة.' });
  }

  await pool.execute('UPDATE admins SET password_hash = ? WHERE id = ?', [await hashPassword(newPassword), req.admin.id]);
  await writeAudit({ req, actorType: 'admin', actorId: req.admin.id, actorName: req.admin.username, actionKey: 'admin_password_changed' });
  res.json({ message: 'تم تغيير كلمة مرور الأدمن.' });
}));

module.exports = router;
