const express = require('express');
const { v4: uuidv4 } = require('uuid');
const router = express.Router();
const multer = require('multer');
const csv = require('csv-parser');
const fs = require('fs');
const path = require('path');
const { createObjectCsvWriter } = require('csv-writer');
const storageService = require('../services/storageService');

// Configure multer for file uploads
// const upload = multer({
//   dest: path.join(__dirname, '../uploads/temp'),
//   limits: { fileSize: 10 * 1024 * 1024 } // 10MB limit
// });

module.exports = (pool, query, authMiddleware) => {
  // Apply authentication middleware to all routes
  router.use(authMiddleware);
  
  const upload = storageService.getUploadMiddleware();
  /**
   * Get all mailing lists
   * GET /api/admin/mailing-lists
   */
  router.get('/', async (req, res, next) => {
    try {
      if (!req.user.is_admin) {
        return res.status(403).json({
          error: true,
          message: 'Admin access required'
        });
      }
      
      // Get all mailing lists with subscriber counts
      const result = await query(`
        SELECT 
          ml.id, 
          ml.name, 
          ml.description, 
          ml.created_at, 
          ml.updated_at,
          COUNT(ms.subscriber_id) AS subscriber_count
        FROM mailing_lists ml
        LEFT JOIN mailing_list_subscribers ms ON ml.id = ms.list_id
        GROUP BY 
          ml.id, ml.name, ml.description, ml.created_at, ml.updated_at
        ORDER BY ml.name;
      `);
      
      res.json(result.rows);
    } catch (error) {
      next(error);
    }
  });
  
  /**
   * Get a single mailing list by ID
   * GET /api/admin/mailing-lists/:id
   */
  router.get('/:id', async (req, res, next) => {
    try {
      const { id } = req.params;
      
      if (!req.user.is_admin) {
        return res.status(403).json({
          error: true,
          message: 'Admin access required'
        });
      }
      
      // Get mailing list with subscriber count
      const result = await query(`
        SELECT 
          ml.id, 
          ml.name, 
          ml.description, 
          ml.created_at, 
          ml.updated_at,
          COUNT(ms.subscriber_id) AS subscriber_count
        FROM mailing_lists ml
        LEFT JOIN mailing_list_subscribers ms ON ml.id = ms.list_id
        WHERE ml.id = $1
        GROUP BY 
          ml.id, ml.name, ml.description, ml.created_at, ml.updated_at;
      `, [id]);
      
      if (result.rows.length === 0) {
        return res.status(404).json({
          error: true,
          message: 'Mailing list not found'
        });
      }
      
      res.json(result.rows[0]);
    } catch (error) {
      next(error);
    }
  });
  
  /**
   * Create a new mailing list
   * POST /api/admin/mailing-lists
   */
  router.post('/', async (req, res, next) => {
    try {
      const { name, description } = req.body;
      
      if (!req.user.is_admin) {
        return res.status(403).json({
          error: true,
          message: 'Admin access required'
        });
      }
      
      // Validate required fields
      if (!name) {
        return res.status(400).json({
          error: true,
          message: 'List name is required'
        });
      }
      
      // Create new mailing list
      const listId = uuidv4();
      const result = await query(
        `INSERT INTO mailing_lists (id, name, description)
         VALUES ($1, $2, $3)
         RETURNING *`,
        [listId, name, description]
      );
      
      res.status(201).json(result.rows[0]);
    } catch (error) {
      next(error);
    }
  });
  
  /**
   * Update a mailing list
   * PUT /api/admin/mailing-lists/:id
   */
  router.put('/:id', async (req, res, next) => {
    try {
      const { id } = req.params;
      const { name, description } = req.body;
      
      if (!req.user.is_admin) {
        return res.status(403).json({
          error: true,
          message: 'Admin access required'
        });
      }
      
      // Validate required fields
      if (!name) {
        return res.status(400).json({
          error: true,
          message: 'List name is required'
        });
      }
      
      // Check if list exists
      const listCheck = await query(
        'SELECT id FROM mailing_lists WHERE id = $1',
        [id]
      );
      
      if (listCheck.rows.length === 0) {
        return res.status(404).json({
          error: true,
          message: 'Mailing list not found'
        });
      }
      
      // Update mailing list
      const result = await query(
        `UPDATE mailing_lists
         SET name = $1, description = $2, updated_at = NOW()
         WHERE id = $3
         RETURNING *`,
        [name, description, id]
      );
      
      res.json(result.rows[0]);
    } catch (error) {
      next(error);
    }
  });
  
  /**
   * Delete a mailing list
   * DELETE /api/admin/mailing-lists/:id
   */
  router.delete('/:id', async (req, res, next) => {
    try {
      const { id } = req.params;
      
      if (!req.user.is_admin) {
        return res.status(403).json({
          error: true,
          message: 'Admin access required'
        });
      }
      
      // Check if list exists
      const listCheck = await query(
        'SELECT id FROM mailing_lists WHERE id = $1',
        [id]
      );
      
      if (listCheck.rows.length === 0) {
        return res.status(404).json({
          error: true,
          message: 'Mailing list not found'
        });
      }
      
      // Begin transaction
      const client = await pool.connect();
      
      try {
        await client.query('BEGIN');
        
        // Delete all subscribers from this list
        await client.query(
          'DELETE FROM mailing_list_subscribers WHERE list_id = $1',
          [id]
        );
        
        // Delete the mailing list
        await client.query(
          'DELETE FROM mailing_lists WHERE id = $1',
          [id]
        );
        
        await client.query('COMMIT');
        
        res.json({
          success: true,
          message: 'Mailing list deleted successfully'
        });
      } catch (error) {
        await client.query('ROLLBACK');
        throw error;
      } finally {
        client.release();
      }
    } catch (error) {
      next(error);
    }
  });
  
  /**
   * Get subscribers for a mailing list
   * GET /api/admin/mailing-lists/:id/subscribers
   */
  router.get('/:id/subscribers', async (req, res, next) => {
    try {
      const { id } = req.params;
      const { page = 0, pageSize = 25, search = '', status } = req.query;
      
      if (!req.user.is_admin) {
        return res.status(403).json({
          error: true,
          message: 'Admin access required'
        });
      }
      
      // Check if list exists
      const listCheck = await query(
        'SELECT id FROM mailing_lists WHERE id = $1',
        [id]
      );
      
      if (listCheck.rows.length === 0) {
        return res.status(404).json({
          error: true,
          message: 'Mailing list not found'
        });
      }
      
      // Prepare query conditions
      const conditions = ['ms.list_id = $1'];
      const queryParams = [id];
      let paramIndex = 2;
      
      if (search) {
        conditions.push(`(
          s.email ILIKE $${paramIndex} OR
          s.first_name ILIKE $${paramIndex} OR
          s.last_name ILIKE $${paramIndex}
        )`);
        queryParams.push(`%${search}%`);
        paramIndex++;
      }
      
      if (status && status !== 'all') {
        conditions.push(`s.status = $${paramIndex}`);
        queryParams.push(status);
        paramIndex++;
      }
      
      // Build WHERE clause
      const whereClause = conditions.length > 0 
        ? `WHERE ${conditions.join(' AND ')}` 
        : '';
      
      // Get total count
      const countQuery = `
        SELECT COUNT(*) as total
        FROM mailing_list_subscribers ms
        JOIN subscribers s ON ms.subscriber_id = s.id
        ${whereClause}
      `;
      
      const countResult = await query(countQuery, queryParams);
      const totalCount = parseInt(countResult.rows[0].total, 10);
      
      // Get filtered count if status filter is applied
      let filteredCount;
      if (status && status !== 'all') {
        const filteredCountQuery = `
          SELECT COUNT(*) as filtered
          FROM mailing_list_subscribers ms
          JOIN subscribers s ON ms.subscriber_id = s.id
          WHERE ms.list_id = $1 AND s.status = $2
        `;
        const filteredCountResult = await query(filteredCountQuery, [id, status]);
        filteredCount = parseInt(filteredCountResult.rows[0].filtered, 10);
      }
      
      // Get subscribers with pagination
      const offset = page * pageSize;
      const subscribersQuery = `
        SELECT 
          s.id,
          s.email,
          s.first_name,
          s.last_name,
          s.status,
          ms.subscribed_at,
          s.last_activity_at
        FROM mailing_list_subscribers ms
        JOIN subscribers s ON ms.subscriber_id = s.id
        ${whereClause}
        ORDER BY s.email
        LIMIT $${paramIndex} OFFSET $${paramIndex + 1}
      `;
      
      queryParams.push(parseInt(pageSize, 10), offset);
      const subscribersResult = await query(subscribersQuery, queryParams);
      
      res.json({
        subscribers: subscribersResult.rows,
        totalCount,
        filteredCount,
        page: parseInt(page, 10),
        pageSize: parseInt(pageSize, 10)
      });
    } catch (error) {
      next(error);
    }
  });
  
  /**
   * Add a subscriber to a mailing list
   * POST /api/admin/mailing-lists/:id/subscribers
   */
  router.post('/:id/subscribers', async (req, res, next) => {
    try {
      const { id } = req.params;
      const { email, firstName, lastName, status = 'active' } = req.body;
      
      if (!req.user.is_admin) {
        return res.status(403).json({
          error: true,
          message: 'Admin access required'
        });
      }
      
      // Validate required fields
      if (!email) {
        return res.status(400).json({
          error: true,
          message: 'Email is required'
        });
      }
      
      // Check if list exists
      const listCheck = await query(
        'SELECT id FROM mailing_lists WHERE id = $1',
        [id]
      );
      
      if (listCheck.rows.length === 0) {
        return res.status(404).json({
          error: true,
          message: 'Mailing list not found'
        });
      }
      
      // Begin transaction
      const client = await pool.connect();
      
      try {
        await client.query('BEGIN');
        
        // Check if subscriber already exists
        let subscriberId;
        const subscriberCheck = await client.query(
          'SELECT id FROM subscribers WHERE email = $1',
          [email]
        );
        
        if (subscriberCheck.rows.length > 0) {
          // Update existing subscriber
          subscriberId = subscriberCheck.rows[0].id;
          await client.query(
            `UPDATE subscribers
             SET first_name = COALESCE($1, first_name),
                 last_name = COALESCE($2, last_name),
                 status = $3,
                 updated_at = NOW()
             WHERE id = $4`,
            [firstName, lastName, status, subscriberId]
          );
        } else {
          // Create new subscriber
          subscriberId = uuidv4();
          await client.query(
            `INSERT INTO subscribers (id, email, first_name, last_name, status)
             VALUES ($1, $2, $3, $4, $5)`,
            [subscriberId, email, firstName, lastName, status]
          );
        }
        
        // Check if subscriber is already on this list
        const listSubscriberCheck = await client.query(
          'SELECT * FROM mailing_list_subscribers WHERE list_id = $1 AND subscriber_id = $2',
          [id, subscriberId]
        );
        
        if (listSubscriberCheck.rows.length === 0) {
          // Add subscriber to list
          await client.query(
            `INSERT INTO mailing_list_subscribers (list_id, subscriber_id)
             VALUES ($1, $2)`,
            [id, subscriberId]
          );
        }
        
        await client.query('COMMIT');
        
        res.status(201).json({
          success: true,
          message: 'Subscriber added to list',
          subscriberId,
          listId: id
        });
      } catch (error) {
        await client.query('ROLLBACK');
        throw error;
      } finally {
        client.release();
      }
    } catch (error) {
      next(error);
    }
  });
  
  /**
   * Import subscribers to a mailing list from CSV
   * POST /api/admin/mailing-lists/import
   */
  router.post('/import', upload.single('file'), async (req, res, next) => {
    try {
      const { listId } = req.body;
      const file = req.file;
      
      if (!req.user.is_admin) {
        return res.status(403).json({
          error: true,
          message: 'Admin access required'
        });
      }
      
      if (!listId) {
        return res.status(400).json({
          error: true,
          message: 'List ID is required'
        });
      }
      
      if (!file) {
        return res.status(400).json({
          error: true,
          message: 'CSV file is required'
        });
      }
      
      // Check if list exists
      const listCheck = await query(
        'SELECT id FROM mailing_lists WHERE id = $1',
        [listId]
      );
      
      if (listCheck.rows.length === 0) {
        return res.status(404).json({
          error: true,
          message: 'Mailing list not found'
        });
      }
      
      // Process the CSV file
      const results = [];
      // const processFile = () => {
      //   return new Promise((resolve, reject) => {
      //     fs.createReadStream(file.path)
      //       .pipe(csv())
      //       .on('data', (data) => results.push(data))
      //       .on('end', () => {
      //         // Clean up temp file
      //         fs.unlink(file.path, (err) => {
      //           if (err) console.error('Error deleting temp file:', err);
      //         });
      //         resolve(results);
      //       })
      //       .on('error', reject);
      //   });
      // };
      const processFile = () => {
        return new Promise((resolve, reject) => {
          // For S3 uploads, file.path won't exist, but file.location will
          const filePath = file.path || file.location;
          
          // If S3 storage, we need to download the file first
          if (!file.path && file.location) {
            // Implementation for S3 file would go here
            // For now, we'll reject as this would need a different approach
            reject(new Error('S3 file processing not implemented'));
            return;
          }
          
          // Local file processing
          fs.createReadStream(file.path)
            .pipe(csv())
            .on('data', (data) => results.push(data))
            .on('end', () => {
              // Clean up temp file - only for local storage
              if (file.path) {
                fs.unlink(file.path, (err) => {
                  if (err) console.error('Error deleting temp file:', err);
                });
              }
              resolve(results);
            })
            .on('error', reject);
        });
      };
      
      const subscribers = await processFile();
      
      // Validate and import subscribers
      if (subscribers.length === 0) {
        return res.status(400).json({
          error: true,
          message: 'CSV file is empty or has invalid format'
        });
      }
      
      // Begin transaction
      const client = await pool.connect();
      let importedCount = 0;
      let errorCount = 0;
      
      try {
        await client.query('BEGIN');
        
        for (const data of subscribers) {
          try {
            // Validate email
            const email = data.email;
            if (!email || !/^[^\s@]+@[^\s@]+\.[^\s@]+$/.test(email)) {
              errorCount++;
              continue;
            }
            
            // Check if subscriber already exists
            let subscriberId;
            const subscriberCheck = await client.query(
              'SELECT id FROM subscribers WHERE email = $1',
              [email]
            );
            
            if (subscriberCheck.rows.length > 0) {
              // Update existing subscriber
              subscriberId = subscriberCheck.rows[0].id;
              await client.query(
                `UPDATE subscribers
                 SET first_name = COALESCE($1, first_name),
                     last_name = COALESCE($2, last_name),
                     status = COALESCE($3, status),
                     updated_at = NOW()
                 WHERE id = $4`,
                [data.first_name, data.last_name, data.status || 'active', subscriberId]
              );
            } else {
              // Create new subscriber
              subscriberId = uuidv4();
              await client.query(
                `INSERT INTO subscribers (id, email, first_name, last_name, status)
                 VALUES ($1, $2, $3, $4, $5)`,
                [subscriberId, email, data.first_name || null, data.last_name || null, data.status || 'active']
              );
            }
            
            // Check if subscriber is already on this list
            const listSubscriberCheck = await client.query(
              'SELECT * FROM mailing_list_subscribers WHERE list_id = $1 AND subscriber_id = $2',
              [listId, subscriberId]
            );
            
            if (listSubscriberCheck.rows.length === 0) {
              // Add subscriber to list
              await client.query(
                `INSERT INTO mailing_list_subscribers (list_id, subscriber_id)
                 VALUES ($1, $2)`,
                [listId, subscriberId]
              );
            }
            
            importedCount++;
          } catch (err) {
            console.error('Error importing subscriber:', err);
            errorCount++;
          }
        }
        
        await client.query('COMMIT');
        
        res.status(200).json({
          success: true,
          message: `Import completed with ${importedCount} subscribers added and ${errorCount} errors`,
          importedCount,
          errorCount,
          listId
        });
      } catch (error) {
        await client.query('ROLLBACK');
        throw error;
      } finally {
        client.release();
      }
    } catch (error) {
      // Clean up temp file on error
      if (req.file) {
        fs.unlink(req.file.path, (err) => {
          if (err) console.error('Error deleting temp file:', err);
        });
      }
      next(error);
    }
  });
  
  /**
   * Export subscribers from a mailing list as CSV
   * GET /api/admin/mailing-lists/:id/export
   */
  router.get('/:id/export', async (req, res, next) => {
    try {
      const { id } = req.params;
      
      if (!req.user.is_admin) {
        return res.status(403).json({
          error: true,
          message: 'Admin access required'
        });
      }
      
      // Check if list exists
      const listCheck = await query(
        'SELECT name FROM mailing_lists WHERE id = $1',
        [id]
      );
      
      if (listCheck.rows.length === 0) {
        return res.status(404).json({
          error: true,
          message: 'Mailing list not found'
        });
      }
      
      const listName = listCheck.rows[0].name;
      
      // Get all subscribers for this list
      const subscribersQuery = `
        SELECT 
          s.email,
          s.first_name,
          s.last_name,
          s.status,
          ms.subscribed_at,
          s.last_activity_at
        FROM mailing_list_subscribers ms
        JOIN subscribers s ON ms.subscriber_id = s.id
        WHERE ms.list_id = $1
        ORDER BY s.email
      `;
      
      const subscribersResult = await query(subscribersQuery, [id]);
      const subscribers = subscribersResult.rows;
      
      // Create a temp file for CSV
      const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
      const fileName = `subscribers-${listName.replace(/[^a-z0-9]/gi, '-').toLowerCase()}-${timestamp}.csv`;
      const tempDir = path.join(__dirname, '../uploads/temp');
      if (!fs.existsSync(tempDir)) {
        fs.mkdirSync(tempDir, { recursive: true });
      }
      const filePath = path.join(__dirname, '../uploads/temp', fileName);
      
      // Create CSV writer
      const csvWriter = createObjectCsvWriter({
        path: filePath,
        header: [
          { id: 'email', title: 'Email' },
          { id: 'first_name', title: 'First Name' },
          { id: 'last_name', title: 'Last Name' },
          { id: 'status', title: 'Status' },
          { id: 'subscribed_at', title: 'Subscribed At' },
          { id: 'last_activity_at', title: 'Last Activity' }
        ]
      });
      
      // Format dates in the data
      const formattedSubscribers = subscribers.map(sub => ({
        ...sub,
        subscribed_at: sub.subscribed_at ? new Date(sub.subscribed_at).toISOString() : '',
        last_activity_at: sub.last_activity_at ? new Date(sub.last_activity_at).toISOString() : ''
      }));
      
      // Write to CSV
      await csvWriter.writeRecords(formattedSubscribers);
      
      // Send file and delete after sending
      res.download(filePath, fileName, (err) => {
        // Delete the temp file after sending
        fs.unlink(filePath, (unlinkErr) => {
          if (unlinkErr) console.error('Error deleting temp file:', unlinkErr);
        });
        
        if (err) {
          console.error('Error sending file:', err);
          if (!res.headersSent) {
            res.status(500).json({
              error: true,
              message: 'Error sending file'
            });
          }
        }
      });
    } catch (error) {
      next(error);
    }
  });
  
  return router;
};