const pool = require('../config/db'); const { logActivity } = require('../services/activityLog'); const sharp = require('sharp'); const path = require('path'); const fs = require('fs'); exports.list = async (req, res) => { try { const [rows] = await pool.query(` SELECT u.id, u.prenom, u.nom, u.societe, u.activite, u.email, u.telephone, u.photo_url, u.merged_display_name, u.site_web, u.role, u.date_adhesion, u.date_echeance, u.invite_par_id, ip.prenom AS invite_par_prenom, ip.nom AS invite_par_nom, u.date_postulation, u.reception_connu, u.reception_inconnu, rc.prenom AS reception_connu_prenom, rc.nom AS reception_connu_nom, ri.prenom AS reception_inconnu_prenom, ri.nom AS reception_inconnu_nom, u.date_entretien_postulation, u.date_demande_whatsapp, u.fonction, u.fonction_emoji, u.kdrive_link FROM users u LEFT JOIN users ip ON ip.id = u.invite_par_id LEFT JOIN users rc ON rc.id = u.reception_connu LEFT JOIN users ri ON ri.id = u.reception_inconnu WHERE u.actif = 1 ORDER BY u.prenom ASC `); res.json(rows); } catch (err) { console.error(err); res.status(500).json({ error: 'Erreur serveur' }); } }; exports.getById = async (req, res) => { try { const [rows] = await pool.query(` SELECT u.*, ip.prenom AS invite_par_prenom, ip.nom AS invite_par_nom, rc.prenom AS reception_connu_prenom, rc.nom AS reception_connu_nom, ri.prenom AS reception_inconnu_prenom, ri.nom AS reception_inconnu_nom FROM users u LEFT JOIN users ip ON ip.id = u.invite_par_id LEFT JOIN users rc ON rc.id = u.reception_connu LEFT JOIN users ri ON ri.id = u.reception_inconnu WHERE u.id = ? `, [req.params.id]); if (rows.length === 0) return res.status(404).json({ error: 'Not found' }); const { password_hash, ...member } = rows[0]; res.json(member); } catch (err) { console.error(err); res.status(500).json({ error: 'Server error' }); } }; exports.update = async (req, res) => { try { const memberId = req.params.id; if (Number(memberId) !== req.user.id && req.user.role !== 'admin') { return res.status(403).json({ error: 'Unauthorized' }); } const { prenom, nom, societe, activite, email, telephone, site_web, date_adhesion, date_echeance, invite_par_id, date_postulation, reception_connu, reception_inconnu, date_entretien_postulation, date_demande_whatsapp, fonction, fonction_emoji, kdrive_link, merged_display_name } = req.body; if (!prenom || !nom) return res.status(400).json({ error: 'Prénom et nom requis' }); const isAdmin = req.user.role === 'admin'; const adminFields = isAdmin ? { date_adhesion: date_adhesion || null, date_echeance: date_echeance || null, invite_par_id: invite_par_id || null, date_postulation: date_postulation || null, reception_connu: reception_connu || null, reception_inconnu: reception_inconnu || null, date_entretien_postulation: date_entretien_postulation || null, date_demande_whatsapp: date_demande_whatsapp || null, fonction: fonction || null, fonction_emoji: fonction_emoji || null, kdrive_link: kdrive_link || null, merged_display_name: merged_display_name || null, } : {}; await pool.query( `UPDATE users SET prenom=?, nom=?, societe=?, activite=?, email=?, telephone=?, site_web=?, date_adhesion=?, date_echeance=?, invite_par_id=?, date_postulation=?, reception_connu=?, reception_inconnu=?, date_entretien_postulation=?, date_demande_whatsapp=?, fonction=?, fonction_emoji=?, kdrive_link=?, merged_display_name=? WHERE id=?`, [prenom, nom, societe || null, activite || null, email || null, telephone || null, site_web || null, adminFields.date_adhesion, adminFields.date_echeance, adminFields.invite_par_id, adminFields.date_postulation, adminFields.reception_connu, adminFields.reception_inconnu, adminFields.date_entretien_postulation, adminFields.date_demande_whatsapp, adminFields.fonction, adminFields.fonction_emoji, adminFields.kdrive_link, adminFields.merged_display_name, memberId] ); logActivity(req, 'membre_modification', { memberId }); res.json({ message: 'Mis à jour' }); } catch (err) { console.error(err); res.status(500).json({ error: 'Erreur serveur' }); } }; exports.uploadPhoto = async (req, res) => { try { if (!req.file) return res.status(400).json({ error: 'No file uploaded' }); const filePath = req.file.path; const ext = path.extname(filePath); const jpgPath = ext === '.jpg' ? filePath : filePath.replace(ext, '.jpg'); try { await sharp(filePath).resize(400, 400, { fit: 'cover', position: 'centre' }).jpeg({ quality: 85 }).toFile(jpgPath); if (jpgPath !== filePath) fs.unlinkSync(filePath); } catch (sharpErr) { console.error('Sharp error, fallback:', sharpErr); if (jpgPath !== filePath) fs.renameSync(filePath, jpgPath); } const finalUrl = `/uploads/${path.basename(jpgPath)}`; const [existing] = await pool.query('SELECT photo_url FROM users WHERE id = ?', [req.user.id]); if (existing[0]?.photo_url) { const oldRelativePath = existing[0].photo_url.replace(/^\//, ''); const oldPath = path.join(__dirname, '..', oldRelativePath); if (fs.existsSync(oldPath)) fs.unlinkSync(oldPath); } await pool.query('UPDATE users SET photo_url = ? WHERE id = ?', [finalUrl, req.user.id]); logActivity(req, 'photo_changement'); res.json({ photo_url: finalUrl }); } catch (err) { console.error(err); res.status(500).json({ error: 'Server error' }); } }; exports.create = async (req, res) => { try { const { prenom, nom, societe, activite, email, telephone, role } = req.body; if (!prenom || !nom || !email) { return res.status(400).json({ error: 'Prénom, nom et email requis' }); } const defaultPassword = 'Bienvenue2026'; const bcrypt = require('bcrypt'); const hash = await bcrypt.hash(defaultPassword, 10); const [result] = await pool.query( 'INSERT INTO users (prenom, nom, societe, activite, email, telephone, role, password_hash, date_adhesion, actif) VALUES (?, ?, ?, ?, ?, ?, ?, ?, CURDATE(), 1)', [prenom, nom, societe || null, activite || null, email, telephone || null, role || 'member', hash] ); res.status(201).json({ id: result.insertId, message: 'Membre créé', defaultPassword: 'Bienvenue2026', }); logActivity(req, 'membre_ajout', { prenom, nom }); } catch (err) { if (err.code === 'ER_DUP_ENTRY') { return res.status(400).json({ error: 'Cet email est déjà utilisé' }); } console.error(err); res.status(500).json({ error: 'Server error' }); } }; exports.remove = async (req, res) => { try { if (req.user.role !== 'admin') return res.status(403).json({ error: 'Admin seulement' }); const memberId = req.params.id; if (Number(memberId) === req.user.id) return res.status(400).json({ error: 'Vous ne pouvez pas vous supprimer vous-même' }); await pool.query('UPDATE users SET actif = 0 WHERE id = ?', [memberId]); logActivity(req, 'membre_desactivation', { memberId }); } catch (err) { console.error(err); res.status(500).json({ error: 'Server error' }); } };