const bcrypt = require('bcryptjs');
const {pool} = require('../config/db');

function mapUser(row) {
  return {
    id: String(row.id),
    name: row.name,
    username: row.username,
    mobile: row.mobile,
    email: row.email,
    role: row.role_name,
    status: row.status,
    shopId: String(row.shop_id),
  };
}

async function listUsers(shopId, query) {
  const params = [shopId];
  let where = 'WHERE u.shop_id = ? AND u.deleted_at IS NULL';
  if (query.search) {
    where += ' AND (u.name LIKE ? OR u.username LIKE ? OR u.mobile LIKE ?)';
    const search = `%${query.search}%`;
    params.push(search, search, search);
  }

  const [rows] = await pool.execute(
    `SELECT u.*, r.role_name
     FROM users u
     INNER JOIN roles r ON r.id = u.role_id
     ${where}
     ORDER BY u.created_at DESC`,
    params,
  );
  return rows.map(mapUser);
}

async function createUser(shopId, createdBy, payload) {
  const [roles] = await pool.execute('SELECT id FROM roles WHERE role_name = ? LIMIT 1', [payload.role || 'Shop Keeper']);
  if (!roles.length) {
    const error = new Error('Invalid role');
    error.statusCode = 422;
    throw error;
  }
  const passwordHash = await bcrypt.hash(payload.password, 12);
  const [result] = await pool.execute(
    `INSERT INTO users (shop_id, role_id, name, username, password_hash, mobile, email, status, created_by)
     VALUES (?, ?, ?, ?, ?, ?, ?, ?, ?)`,
    [
      shopId,
      roles[0].id,
      payload.name,
      payload.username,
      passwordHash,
      payload.mobile || null,
      payload.email || null,
      payload.status || 'Active',
      createdBy,
    ],
  );

  const [rows] = await pool.execute(
    'SELECT u.*, r.role_name FROM users u INNER JOIN roles r ON r.id = u.role_id WHERE u.id = ?',
    [result.insertId],
  );
  return mapUser(rows[0]);
}

async function updateUser(shopId, updatedBy, id, payload) {
  const passwordHash = payload.password ? await bcrypt.hash(payload.password, 12) : null;
  await pool.execute(
    `UPDATE users
     SET name = COALESCE(?, name),
         mobile = ?,
         email = ?,
         password_hash = COALESCE(?, password_hash),
         status = COALESCE(?, status),
         updated_by = ?
     WHERE shop_id = ? AND id = ? AND deleted_at IS NULL`,
    [payload.name || null, payload.mobile || null, payload.email || null, passwordHash, payload.status || null, updatedBy, shopId, id],
  );

  const [rows] = await pool.execute(
    'SELECT u.*, r.role_name FROM users u INNER JOIN roles r ON r.id = u.role_id WHERE u.shop_id = ? AND u.id = ?',
    [shopId, id],
  );
  return mapUser(rows[0]);
}

async function deleteUser(shopId, updatedBy, id) {
  await pool.execute('UPDATE users SET deleted_at = NOW(), updated_by = ? WHERE shop_id = ? AND id = ?', [updatedBy, shopId, id]);
}

module.exports = {createUser, deleteUser, listUsers, updateUser};
