const pool = require('../config/db');

class Message {
  // Create a new message
  static async create(senderId, subject, message, recipients) {
    try {
      await pool.query('START TRANSACTION');
      
      // Insert the main message
      const [messageResult] = await pool.query(
        'INSERT INTO messages (subject, message, message_from) VALUES (?, ?, ?)',
        [subject, message, senderId]
      );
      const messageId = messageResult.insertId;

    // First, ensure recipients is an array
    if (!Array.isArray(recipients)) {
    // If it's a string, try to parse it
    if (typeof recipients === 'string') {
        try {
        recipients = JSON.parse(recipients);
        } catch (e) {
        throw new Error('Invalid recipients format');
        }
    } else {
        throw new Error('Recipients must be an array');
    }
    }

    // Now safely map the recipients
    const recipientValues = recipients.map(userId => [messageId, parseInt(userId)]);

    await pool.query(
    'INSERT INTO message_recepient (message_id, user_id) VALUES ?',
    [recipientValues]
    );

      await pool.query('COMMIT');
      return messageId;
    } catch (error) {
      await pool.query('ROLLBACK');
      throw error;
    }
  }

  // Add attachments to a message
  static async addAttachments(messageId, attachments) {
    try {
      const attachmentValues = attachments.map(attachment => [
        messageId,
        attachment.type,
        attachment.url
      ]);
      
      await pool.query(
        'INSERT INTO message_attachments (message_id, attachment_type, attachment_url) VALUES ?',
        [attachmentValues]
      );
    } catch (error) {
      throw error;
    }
  }

static async getAllForUser(userId) {
  try {
    // Get both messages received by the user AND messages created by the user
    const [messages] = await pool.query(`
      SELECT m.*, u.first_name as sender_first_name, u.last_name as sender_last_name,
             u.profile_url as sender_profile_url, mr.is_read, mr.unread_replies_count,
             (m.message_from = ?) as is_mine
      FROM messages m
      JOIN users u ON m.message_from = u.id
      LEFT JOIN message_recepient mr ON m.id = mr.message_id AND mr.user_id = ?
      WHERE m.message_from = ? OR mr.user_id = ?
    `, [userId, userId, userId, userId]);

    const messagesWithReplies = await Promise.all(messages.map(async message => {
      const [attachments] = await pool.query(
        'SELECT * FROM message_attachments WHERE message_id = ?',
        [message.id]
      );

      const [replies] = await pool.query(`
        SELECT r.*, u.first_name, u.last_name, u.profile_url,
               (r.user_id = ?) as is_mine
        FROM message_replies r
        JOIN users u ON r.user_id = u.id
        WHERE r.message_id = ?
        ORDER BY r.created_at ASC
      `, [userId, message.id]);

      const repliesWithAttachments = await Promise.all(replies.map(async reply => {
        const [replyAttachments] = await pool.query(
          'SELECT * FROM reply_attachments WHERE reply_id = ?',
          [reply.id]
        );
        return {
          ...reply,
          attachments: replyAttachments
        };
      }));

      // Determine last activity: last reply date or message created_at
      const lastReplyDate = repliesWithAttachments.length > 0
        ? new Date(repliesWithAttachments[repliesWithAttachments.length - 1].created_at)
        : new Date(message.created_at);

      return {
        ...message,
        attachments,
        replies: repliesWithAttachments,
        last_activity: lastReplyDate
      };
    }));

    // Sort messages by last_activity descending
    messagesWithReplies.sort((a, b) => b.last_activity - a.last_activity);

    return messagesWithReplies;
  } catch (error) {
    console.error("Error fetching messages:", error);
    throw error;
  }
}


  static async getByIdForUser(messageId, userId) {
  try {
    const [messages] = await pool.query(`
      SELECT m.*, u.first_name as sender_first_name, u.last_name as sender_last_name,
             u.profile_url as sender_profile_url, mr.is_read
      FROM messages m
      JOIN users u ON m.message_from = u.id
      LEFT JOIN message_recepient mr ON m.id = mr.message_id AND mr.user_id = ?
      WHERE m.id = ? AND (m.message_from = ? OR mr.user_id = ?)
    `, [userId, messageId, userId, userId]);
    
    if (messages.length === 0) return null;
    
    const message = messages[0];
    
    // Get attachments
    const [attachments] = await pool.query(
      'SELECT * FROM message_attachments WHERE message_id = ?',
      [messageId]
    );
    
    // Get replies
    const [replies] = await pool.query(`
      SELECT r.*, u.first_name, u.last_name, u.profile_url
      FROM message_replies r
      JOIN users u ON r.user_id = u.id
      WHERE r.message_id = ?
      ORDER BY r.created_at ASC
    `, [messageId]);
    
    // Get reply attachments
    const repliesWithAttachments = await Promise.all(replies.map(async reply => {
      const [replyAttachments] = await pool.query(
        'SELECT * FROM reply_attachments WHERE reply_id = ?',
        [reply.id]
      );
      return {
        ...reply,
        attachments: replyAttachments
      };
    }));
    
    return {
      ...message,
      attachments: attachments,
      replies: repliesWithAttachments
    };
  } catch (error) {
    throw error;
  }
}

  // Mark a message as read
  static async markAsRead(messageId, userId) {
    console.log(messageId)
    console.log(userId)
    try {
      await pool.query(
        'UPDATE message_recepient SET is_read = TRUE, unread_replies_count = 0 WHERE message_id = ? AND user_id = ?',
        [messageId, userId]
      );
      await pool.query(
        'UPDATE messages SET has_unread_replies = 0 WHERE id = ? AND message_from = ?',
        [messageId, userId]
      );
      return true;
    } catch (error) {
      throw error;
    }
  }

  // Delete a message for a specific recipient
  static async deleteForRecipient(messageId, userId) {
    try {
      const [result] = await pool.query(
        'DELETE FROM message_recepient WHERE message_id = ? AND user_id = ?',
        [messageId, userId]
      );
      return result.affectedRows > 0;
    } catch (error) {
      throw error;
    }
  }

  // Add a reply to a message
  static async addReply(messageId, userId, replyText) {
    try {
      const [result] = await pool.query(
        'INSERT INTO message_replies (message_id, user_id, reply) VALUES (?, ?, ?)',
        [messageId, userId, replyText]
      );
      return result.insertId;
    } catch (error) {
      throw error;
    }
  }

  // Add attachments to a reply
  static async addReplyAttachments(replyId, attachments) {
    try {
      const attachmentValues = attachments.map(attachment => [
        replyId,
        attachment.type,
        attachment.url
      ]);
      
      await pool.query(
        'INSERT INTO reply_attachments (reply_id, attachment_type, attachment_url) VALUES ?',
        [attachmentValues]
      );
    } catch (error) {
      throw error;
    }
  }

    // Get count of unread messages for a user
    static async getUnreadCount(userId) {
    try {
        const [result] = await pool.query(
        'SELECT COUNT(*) as unread_count FROM message_recepient WHERE user_id = ? AND is_read = FALSE',
        [userId]
        );
        return result[0].unread_count;
    } catch (error) {
        throw error;
    }
    }


}

module.exports = Message;