const db = require('../../database/database'); class MailTemplateRepository { _mapRow(row) { if (!row) return null; return { id: Number(row.id), template_type: row.template_type, name: row.name, subject: row.subject, html_content: row.html_content, is_active: row.is_active === 1 || row.is_active === true, is_archived: row.is_archived === 1 || row.is_archived === true, archived_at: row.archived_at, created_by: row.created_by, updated_by: row.updated_by, created_at: row.created_at, updated_at: row.updated_at, }; } async list({ includeArchived = false, templateType } = {}) { const where = []; const params = []; if (!includeArchived) { where.push('is_archived = 0'); } if (templateType) { where.push('template_type = ?'); params.push(templateType); } const whereClause = where.length ? `WHERE ${where.join(' AND ')}` : ''; const [rows] = await db.query( `SELECT * FROM mail_templates ${whereClause} ORDER BY template_type ASC, is_active DESC, updated_at DESC`, params ); return (rows || []).map((row) => this._mapRow(row)); } async getById(id) { const [rows] = await db.query( `SELECT * FROM mail_templates WHERE id = ? LIMIT 1`, [id] ); return this._mapRow(rows?.[0]); } async create(payload) { const [result] = await db.query( `INSERT INTO mail_templates (template_type, name, subject, html_content, is_active, is_archived, created_by, updated_by) VALUES (?, ?, ?, ?, 0, 0, ?, ?)`, [ payload.template_type, payload.name, payload.subject || null, payload.html_content, payload.userId || null, payload.userId || null, ] ); return this.getById(result.insertId); } async update(id, payload) { const fields = []; const values = []; if (payload.template_type !== undefined) { fields.push('template_type = ?'); values.push(payload.template_type); } if (payload.name !== undefined) { fields.push('name = ?'); values.push(payload.name); } if (payload.subject !== undefined) { fields.push('subject = ?'); values.push(payload.subject || null); } if (payload.html_content !== undefined) { fields.push('html_content = ?'); values.push(payload.html_content); } fields.push('updated_by = ?'); values.push(payload.userId || null); if (!fields.length) return this.getById(id); values.push(id); const [result] = await db.query( `UPDATE mail_templates SET ${fields.join(', ')}, updated_at = NOW() WHERE id = ?`, values ); if (!result?.affectedRows) return null; return this.getById(id); } async activate(id, userId) { const conn = await db.getConnection(); try { await conn.beginTransaction(); const [targetRows] = await conn.query( `SELECT id, template_type, is_archived FROM mail_templates WHERE id = ? LIMIT 1 FOR UPDATE`, [id] ); const target = targetRows?.[0]; if (!target) { await conn.rollback(); return null; } if (target.is_archived === 1 || target.is_archived === true) { const error = new Error('Archived templates cannot be activated'); error.status = 400; throw error; } await conn.query( `UPDATE mail_templates SET is_active = 0, updated_by = ?, updated_at = NOW() WHERE template_type = ?`, [userId || null, target.template_type] ); await conn.query( `UPDATE mail_templates SET is_active = 1, is_archived = 0, archived_at = NULL, updated_by = ?, updated_at = NOW() WHERE id = ?`, [userId || null, id] ); await conn.commit(); } catch (error) { await conn.rollback(); throw error; } finally { conn.release(); } return this.getById(id); } async archive(id, userId) { const [result] = await db.query( `UPDATE mail_templates SET is_archived = 1, is_active = 0, archived_at = NOW(), updated_by = ?, updated_at = NOW() WHERE id = ?`, [userId || null, id] ); if (!result?.affectedRows) return null; return this.getById(id); } async delete(id) { const [result] = await db.query('DELETE FROM mail_templates WHERE id = ?', [id]); return Number(result?.affectedRows || 0) > 0; } } module.exports = new MailTemplateRepository();