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 unarchive(id, userId) {
    const [result] = await db.query(
      `UPDATE mail_templates
       SET is_archived = 0,
           archived_at = NULL,
           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();
