const express = require('express');
const { v4: uuidv4 } = require('uuid');
const router = express.Router();
const nodemailer = require('nodemailer');
const config = require('../config');

// Create email transporter
const createTransporter = () => {
  return nodemailer.createTransport({
    host: config.email.host,
    port: config.email.port,
    auth: {
      user: config.email.user,
      pass: config.email.pass
    }
  });
};

module.exports = (pool, query, authMiddleware) => {
  // Apply authentication middleware to all routes
  router.use(authMiddleware);
  
  /**
   * Get all email templates
   * GET /api/admin/email-templates
   */
  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 settings with 'email_templates' category
      const result = await query(
        'SELECT * FROM system_settings WHERE category = $1 ORDER BY key',
        ['email_templates']
      );
      
      // Transform settings into template objects
      const templates = result.rows.map(setting => {
        try {
          // Parse the template data from the JSON value
          const templateData = JSON.parse(setting.value);
          return {
            id: setting.key,
            ...templateData
          };
        } catch (e) {
          console.error(`Failed to parse template setting: ${setting.key}`, e);
          return null;
        }
      }).filter(Boolean); // Remove any null entries
      
      res.json(templates);
    } catch (error) {
      next(error);
    }
  });
  
  /**
   * Get templates by type
   * GET /api/admin/email-templates/type/:type
   */
  router.get('/type/:type', async (req, res, next) => {
    try {
      const { type } = req.params;
      
      if (!req.user.is_admin) {
        return res.status(403).json({
          error: true,
          message: 'Admin access required'
        });
      }
      
      // Get all settings with 'email_templates' category
      const result = await query(
        'SELECT * FROM system_settings WHERE category = $1 ORDER BY key',
        ['email_templates']
      );
      
      // Transform settings into template objects and filter by type
      const templates = result.rows
        .map(setting => {
          try {
            // Parse the template data from the JSON value
            const templateData = JSON.parse(setting.value);
            if (templateData.type === type) {
              return {
                id: setting.key,
                ...templateData
              };
            }
            return null;
          } catch (e) {
            console.error(`Failed to parse template setting: ${setting.key}`, e);
            return null;
          }
        })
        .filter(Boolean); // Remove any null entries
      
      res.json(templates);
    } catch (error) {
      next(error);
    }
  });
  
  /**
   * Get default template for a type
   * GET /api/admin/email-templates/default/:type
   */
  router.get('/default/:type', async (req, res, next) => {
    try {
      const { type } = req.params;
      
      if (!req.user.is_admin) {
        return res.status(403).json({
          error: true,
          message: 'Admin access required'
        });
      }
      
      // Get all settings with 'email_templates' category
      const result = await query(
        'SELECT * FROM system_settings WHERE category = $1 ORDER BY key',
        ['email_templates']
      );
      
      // Find the default template for the specified type
      let defaultTemplate = null;
      
      for (const setting of result.rows) {
        try {
          const templateData = JSON.parse(setting.value);
          if (templateData.type === type && templateData.isDefault) {
            defaultTemplate = {
              id: setting.key,
              ...templateData
            };
            break;
          }
        } catch (e) {
          console.error(`Failed to parse template setting: ${setting.key}`, e);
        }
      }
      
      if (defaultTemplate) {
        res.json(defaultTemplate);
      } else {
        res.status(404).json({
          error: true,
          message: `No default template found for type: ${type}`
        });
      }
    } catch (error) {
      next(error);
    }
  });
  
  /**
   * Get a single template by ID
   * GET /api/admin/email-templates/: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 the setting by key
      const result = await query(
        'SELECT * FROM system_settings WHERE key = $1',
        [id]
      );
      
      if (result.rows.length === 0) {
        return res.status(404).json({
          error: true,
          message: 'Template not found'
        });
      }
      
      try {
        // Parse the template data from the JSON value
        const templateData = JSON.parse(result.rows[0].value);
        res.json({
          id: result.rows[0].key,
          ...templateData
        });
      } catch (e) {
        console.error(`Failed to parse template setting: ${id}`, e);
        return res.status(500).json({
          error: true,
          message: 'Failed to parse template data'
        });
      }
    } catch (error) {
      next(error);
    }
  });
  
  /**
   * Create a new template
   * POST /api/admin/email-templates
   */
  router.post('/', async (req, res, next) => {
    try {
      const { name, type, subject, content, isDefault } = req.body;
      
      
      if (!req.user.is_admin) {
        return res.status(403).json({
          error: true,
          message: 'Admin access required'
        });
      }
      
      // Validate required fields
      if (!name || !type || !subject || !content) {
        return res.status(400).json({
          error: true,
          message: 'Name, type, subject, and content are required'
        });
      }
      
      // Begin transaction for potential default template updates
      const client = await pool.connect();
      
      try {
        await client.query('BEGIN');
        
        // Generate a unique key for the setting
        const templateKey = `email_template_${Date.now()}`;
        
        // Create the template object
        const templateData = {
          name,
          type,
          subject,
          content,
          isDefault: isDefault || false,
          createdAt: new Date().toISOString()
        };
        
        // If this template should be the default, unset any existing defaults
        if (templateData.isDefault) {
          // Get all settings with 'email_templates' category
          const existingTemplates = await client.query(
            'SELECT * FROM system_settings WHERE category = $1',
            ['email_templates']
          );
          
          // Find and update any existing default templates of the same type
          for (const setting of existingTemplates.rows) {
            try {
              const existingData = JSON.parse(setting.value);
              if (existingData.type === type && existingData.isDefault) {
                existingData.isDefault = false;
                existingData.updatedAt = new Date().toISOString();
                
                await client.query(
                  'UPDATE system_settings SET value = $1, updated_at = NOW() WHERE key = $2',
                  [JSON.stringify(existingData), setting.key]
                );
              }
            } catch (e) {
              console.error(`Failed to parse template setting: ${setting.key}`, e);
            }
          }
        }
        
        // Insert the new template
        await client.query(
          'INSERT INTO system_settings (key, value, category) VALUES ($1, $2, $3)',
          [templateKey, JSON.stringify(templateData), 'email_templates']
        );
        
        await client.query('COMMIT');
        
        res.status(201).json({
          id: templateKey,
          ...templateData
        });
      } catch (error) {
        await client.query('ROLLBACK');
        throw error;
      } finally {
        client.release();
      }
    } catch (error) {
      next(error);
    }
  });
  
  /**
   * Update a template
   * PUT /api/admin/email-templates/:id
   */
  router.put('/:id', async (req, res, next) => {
    try {
      const { id } = req.params;
      const { name, type, subject, content, isDefault } = req.body;
      
      
      if (!req.user.is_admin) {
        return res.status(403).json({
          error: true,
          message: 'Admin access required'
        });
      }
      
      // Validate required fields
      if (!name || !type || !subject || !content) {
        return res.status(400).json({
          error: true,
          message: 'Name, type, subject, and content are required'
        });
      }
      
      // Begin transaction for potential default template updates
      const client = await pool.connect();
      
      try {
        await client.query('BEGIN');
        
        // Check if the template exists
        const templateCheck = await client.query(
          'SELECT * FROM system_settings WHERE key = $1',
          [id]
        );
        
        if (templateCheck.rows.length === 0) {
          await client.query('ROLLBACK');
          return res.status(404).json({
            error: true,
            message: 'Template not found'
          });
        }
        
        // Parse the existing template data
        let existingData;
        try {
          existingData = JSON.parse(templateCheck.rows[0].value);
        } catch (e) {
          await client.query('ROLLBACK');
          return res.status(500).json({
            error: true,
            message: 'Failed to parse existing template data'
          });
        }
        
        // Create the updated template object
        const templateData = {
          name,
          type,
          subject,
          content,
          isDefault: isDefault !== undefined ? isDefault : existingData.isDefault,
          createdAt: existingData.createdAt,
          updatedAt: new Date().toISOString()
        };
        
        // If this template should be the default, unset any existing defaults
        if (templateData.isDefault && (!existingData.isDefault || existingData.type !== type)) {
          // Get all settings with 'email_templates' category
          const existingTemplates = await client.query(
            'SELECT * FROM system_settings WHERE category = $1',
            ['email_templates']
          );
          
          // Find and update any existing default templates of the same type
          for (const setting of existingTemplates.rows) {
            if (setting.key === id) continue; // Skip the current template
            
            try {
              const otherData = JSON.parse(setting.value);
              if (otherData.type === type && otherData.isDefault) {
                otherData.isDefault = false;
                otherData.updatedAt = new Date().toISOString();
                
                await client.query(
                  'UPDATE system_settings SET value = $1, updated_at = NOW() WHERE key = $2',
                  [JSON.stringify(otherData), setting.key]
                );
              }
            } catch (e) {
              console.error(`Failed to parse template setting: ${setting.key}`, e);
            }
          }
        }
        
        // Update the template
        await client.query(
          'UPDATE system_settings SET value = $1, updated_at = NOW() WHERE key = $2',
          [JSON.stringify(templateData), id]
        );
        
        await client.query('COMMIT');
        
        res.json({
          id,
          ...templateData
        });
      } catch (error) {
        await client.query('ROLLBACK');
        throw error;
      } finally {
        client.release();
      }
    } catch (error) {
      next(error);
    }
  });
  
  /**
   * Delete a template
   * DELETE /api/admin/email-templates/: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 the template exists and is not a default template
      const templateCheck = await query(
        'SELECT * FROM system_settings WHERE key = $1',
        [id]
      );
      
      if (templateCheck.rows.length === 0) {
        return res.status(404).json({
          error: true,
          message: 'Template not found'
        });
      }
      
      // Parse the template data to check if it's a default template
      try {
        const templateData = JSON.parse(templateCheck.rows[0].value);
        if (templateData.isDefault) {
          return res.status(400).json({
            error: true,
            message: 'Cannot delete a default template. Please set another template as default first.'
          });
        }
      } catch (e) {
        console.error(`Failed to parse template setting: ${id}`, e);
      }
      
      // Delete the template
      await query(
        'DELETE FROM system_settings WHERE key = $1',
        [id]
      );
      
      res.json({
        success: true,
        message: 'Template deleted successfully'
      });
    } catch (error) {
      next(error);
    }
  });
  
  /**
   * Send a test email using a template
   * POST /api/admin/email-templates/:id/test
   */
  router.post('/:id/test', async (req, res, next) => {
    try {
      const { id } = req.params;
      const { email, variables } = req.body;
      
      
      if (!req.user.is_admin) {
        return res.status(403).json({
          error: true,
          message: 'Admin access required'
        });
      }
      
      // Validate email address
      if (!email) {
        return res.status(400).json({
          error: true,
          message: 'Email address is required'
        });
      }
      
      // Check if the template exists
      const templateCheck = await query(
        'SELECT * FROM system_settings WHERE key = $1',
        [id]
      );
      
      if (templateCheck.rows.length === 0) {
        return res.status(404).json({
          error: true,
          message: 'Template not found'
        });
      }
      
      // Parse the template data
      let templateData;
      try {
        templateData = JSON.parse(templateCheck.rows[0].value);
      } catch (e) {
        console.error(`Failed to parse template setting: ${id}`, e);
        return res.status(500).json({
          error: true,
          message: 'Failed to parse template data'
        });
      }
      
      // Replace variables in template
      let emailContent = templateData.content;
      let emailSubject = templateData.subject;
      
      if (variables) {
        for (const [key, value] of Object.entries(variables)) {
          const placeholder = `{{${key}}}`;
          emailContent = emailContent.replace(new RegExp(placeholder, 'g'), value);
          emailSubject = emailSubject.replace(new RegExp(placeholder, 'g'), value);
        }
      }
      
      // Create a transporter
      const transporter = createTransporter();
      
      // Send the test email
      await transporter.sendMail({
        from: config.email.reply,
        to: email,
        subject: `[TEST] ${emailSubject}`,
        html: emailContent
      });
      
      res.json({
        success: true,
        message: `Test email sent to ${email}`
      });
    } catch (error) {
      next(error);
    }
  });
  
  /**
   * Utility function to get a template by type
   * @param {string} type - Template type
   * @returns {Promise<Object|null>} Template object or null if not found
   */
  async function getTemplateByType(type) {
    try {
      // Get all settings with 'email_templates' category
      const result = await query(
        'SELECT * FROM system_settings WHERE category = $1',
        ['email_templates']
      );
      
      // Find the default template for the specified type
      let defaultTemplate = null;
      
      for (const setting of result.rows) {
        try {
          const templateData = JSON.parse(setting.value);
          if (templateData.type === type && templateData.isDefault) {
            defaultTemplate = {
              id: setting.key,
              ...templateData
            };
            break;
          }
        } catch (e) {
          console.error(`Failed to parse template setting: ${setting.key}`, e);
        }
      }
      
      return defaultTemplate;
    } catch (error) {
      console.error('Error getting template by type:', error);
      return null;
    }
  }

  return router;
};