const nocoDB = require('../services/nocodb');
const emailService = require('../services/email');
const representAPI = require('../services/represent-api');
const { generateSlug, validateSlug } = require('../utils/validators');
const multer = require('multer');
const path = require('path');
const fs = require('fs');

// Configure multer for file uploads
const storage = multer.diskStorage({
  destination: function (req, file, cb) {
    const uploadDir = path.join(__dirname, '../public/uploads');
    // Ensure the upload directory exists
    if (!fs.existsSync(uploadDir)) {
      fs.mkdirSync(uploadDir, { recursive: true });
    }
    cb(null, uploadDir);
  },
  filename: function (req, file, cb) {
    // Generate unique filename with timestamp
    const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1E9);
    cb(null, 'cover-' + uniqueSuffix + path.extname(file.originalname));
  }
});

const upload = multer({
  storage: storage,
  limits: {
    fileSize: 5 * 1024 * 1024 // 5MB limit
  },
  fileFilter: function (req, file, cb) {
    // Accept only image files
    const allowedTypes = /jpeg|jpg|png|gif|webp/;
    const extname = allowedTypes.test(path.extname(file.originalname).toLowerCase());
    const mimetype = allowedTypes.test(file.mimetype);
    
    if (mimetype && extname) {
      return cb(null, true);
    } else {
      cb(new Error('Only image files are allowed (jpeg, jpg, png, gif, webp)'));
    }
  }
});

const VALID_CAMPAIGN_STATUSES = ['draft', 'active', 'paused', 'archived'];

const normalizeTargetLevels = (rawLevels) => {
  if (Array.isArray(rawLevels)) {
    return rawLevels;
  }

  if (typeof rawLevels === 'string' && rawLevels.length > 0) {
    return rawLevels.split(',').map(level => level.trim()).filter(Boolean);
  }

  return [];
};

const normalizeStatus = (rawStatus, fallback = 'draft') => {
  if (!rawStatus) {
    return fallback;
  }

  const status = String(rawStatus).toLowerCase();
  return VALID_CAMPAIGN_STATUSES.includes(status) ? status : fallback;
};

// Helper function to cache representatives
async function cacheRepresentatives(postalCode, representatives, representData) {
  try {
    // Cache the postal code info
    await nocoDB.storePostalCodeInfo({
      postal_code: postalCode,
      city: representData.city,
      province: representData.province
    });
    
    // Cache representatives using the existing method
    const result = await nocoDB.storeRepresentatives(postalCode, representatives);
    
    if (result.success) {
      console.log(`Successfully cached ${result.count} representatives for ${postalCode}`);
    } else {
      console.log(`Partial success caching representatives for ${postalCode}: ${result.error || 'unknown error'}`);
    }
  } catch (error) {
    console.log(`Failed to cache representatives for ${postalCode}:`, error.message);
    // Don't throw - caching is optional and should never break the main flow
  }
}

class CampaignsController {
  // Get public campaigns (no authentication required)
  async getPublicCampaigns(req, res, next) {
    try {
      const campaigns = await nocoDB.getAllCampaigns();
      
      // Filter to only active campaigns and normalize data structure
      const activeCampaigns = await Promise.all(
        campaigns
          .filter(campaign => {
            const status = normalizeStatus(campaign['Status'] || campaign.status);
            return status === 'active';
          })
          .map(async (campaign) => {
            const id = campaign.ID || campaign.Id || campaign.id;
            
            // Debug: Log specific fields we're looking for
            console.log(`Campaign ${id}:`, {
              'Show Call Count': campaign['Show Call Count'],
              'show_call_count': campaign.show_call_count,
              'Show Email Count': campaign['Show Email Count'],
              'show_email_count': campaign.show_email_count
            });
            
            // Get email count if show_email_count is enabled
            let emailCount = null;
            const showEmailCount = campaign['Show Email Count'] || campaign.show_email_count;
            console.log(`Getting email count for campaign ID: ${id}, showEmailCount: ${showEmailCount}`);
            if (showEmailCount && id != null) {
              emailCount = await nocoDB.getCampaignEmailCount(id);
              console.log(`Email count result: ${emailCount}`);
            }

            // Get call count if show_call_count is enabled
            let callCount = null;
            const showCallCount = campaign['Show Call Count'] || campaign.show_call_count;
            console.log(`Getting call count for campaign ID: ${id}, showCallCount: ${showCallCount}`);
            if (showCallCount && id != null) {
              callCount = await nocoDB.getCampaignCallCount(id);
              console.log(`Call count result: ${callCount}`);
            }

            const rawTargetLevels = campaign['Target Government Levels'] || campaign.target_government_levels;
            const normalizedTargetLevels = normalizeTargetLevels(rawTargetLevels);
            
            // Return only public-facing information
            return {
              id,
              slug: campaign['Campaign Slug'] || campaign.slug,
              title: campaign['Campaign Title'] || campaign.title,
              description: campaign['Description'] || campaign.description,
              call_to_action: campaign['Call to Action'] || campaign.call_to_action,
              cover_photo: campaign['Cover Photo'] || campaign.cover_photo,
              show_email_count: showEmailCount,
              show_call_count: showCallCount,
              target_government_levels: normalizedTargetLevels,
              created_at: campaign.CreatedAt || campaign.created_at,
              emailCount,
              callCount
            };
          })
      );

      res.json({
        success: true,
        campaigns: activeCampaigns
      });
    } catch (error) {
      console.error('Get public campaigns error:', error);
      res.status(500).json({
        success: false,
        error: 'Failed to retrieve campaigns',
        message: error.message
      });
    }
  }

  // Get all campaigns (for admin panel)
  async getAllCampaigns(req, res, next) {
    try {
      const campaigns = await nocoDB.getAllCampaigns();
      
      // Get email counts for each campaign and normalize data structure
      const campaignsWithCounts = await Promise.all(campaigns.map(async (campaign) => {
        const id = campaign.ID || campaign.Id || campaign.id;
        let emailCount = 0;
        if (id != null) {
          emailCount = await nocoDB.getCampaignEmailCount(id);
        }

        const rawTargetLevels = campaign['Target Government Levels'] || campaign.target_government_levels;
        const normalizedTargetLevels = normalizeTargetLevels(rawTargetLevels);
        
        // Normalize campaign data structure for frontend
        return {
          id,
          slug: campaign['Campaign Slug'] || campaign.slug,
          title: campaign['Campaign Title'] || campaign.title,
          description: campaign['Description'] || campaign.description,
          email_subject: campaign['Email Subject'] || campaign.email_subject,
          email_body: campaign['Email Body'] || campaign.email_body,
          call_to_action: campaign['Call to Action'] || campaign.call_to_action,
          cover_photo: campaign['Cover Photo'] || campaign.cover_photo,
          status: normalizeStatus(campaign['Status'] || campaign.status),
          allow_smtp_email: campaign['Allow SMTP Email'] || campaign.allow_smtp_email,
          allow_mailto_link: campaign['Allow Mailto Link'] || campaign.allow_mailto_link,
          collect_user_info: campaign['Collect User Info'] || campaign.collect_user_info,
          show_email_count: campaign['Show Email Count'] || campaign.show_email_count,
          allow_email_editing: campaign['Allow Email Editing'] || campaign.allow_email_editing,
          target_government_levels: normalizedTargetLevels,
          created_at: campaign.CreatedAt || campaign.created_at,
          updated_at: campaign.UpdatedAt || campaign.updated_at,
          created_by_user_id: campaign['Created By User ID'] || campaign.created_by_user_id || null,
          created_by_user_email: campaign['Created By User Email'] || campaign.created_by_user_email || null,
          created_by_user_name: campaign['Created By User Name'] || campaign.created_by_user_name || null,
          emailCount
        };
      }));

      let filteredCampaigns = campaignsWithCounts;

      if (req.user && !req.user.isAdmin) {
        const sessionUserId = req.user.id != null ? String(req.user.id) : (req.session?.userId != null ? String(req.session.userId) : null);
        const sessionUserEmail = req.user.email ? String(req.user.email).toLowerCase() : (req.session?.userEmail ? String(req.session.userEmail).toLowerCase() : null);

        filteredCampaigns = campaignsWithCounts.filter((campaign) => {
          const createdById = campaign.created_by_user_id != null ? String(campaign.created_by_user_id) : null;
          const createdByEmail = campaign.created_by_user_email ? String(campaign.created_by_user_email).toLowerCase() : null;

          return (
            (sessionUserId && createdById && createdById === sessionUserId) ||
            (sessionUserEmail && createdByEmail && createdByEmail === sessionUserEmail)
          );
        });
      }

      res.json({
        success: true,
        campaigns: filteredCampaigns
      });
    } catch (error) {
      console.error('Get campaigns error:', error);
      res.status(500).json({
        success: false,
        error: 'Failed to retrieve campaigns',
        message: error.message,
        details: error.response?.data || null
      });
    }
  }

  // Get single campaign by ID (for admin)
  async getCampaignById(req, res, next) {
    try {
      const { id } = req.params;
      const campaign = await nocoDB.getCampaignById(id);
      
      if (!campaign) {
        return res.status(404).json({
          success: false,
          error: 'Campaign not found'
        });
      }

      // Debug logging
      console.log('Campaign object keys:', Object.keys(campaign));
      console.log('Campaign ID field:', campaign.ID, campaign.Id, campaign.id);
      
      const normalizedId = campaign.ID || campaign.Id || campaign.id;
      console.log('Using normalized ID:', normalizedId);
      
      const emailCount = await nocoDB.getCampaignEmailCount(normalizedId);
      
      // Normalize campaign data structure for frontend
      res.json({
        success: true,
        campaign: {
          id: normalizedId,
          slug: campaign['Campaign Slug'] || campaign.slug,
          title: campaign['Campaign Title'] || campaign.title,
          description: campaign['Description'] || campaign.description,
          email_subject: campaign['Email Subject'] || campaign.email_subject,
          email_body: campaign['Email Body'] || campaign.email_body,
          call_to_action: campaign['Call to Action'] || campaign.call_to_action,
          cover_photo: campaign['Cover Photo'] || campaign.cover_photo,
          status: normalizeStatus(campaign['Status'] || campaign.status),
          allow_smtp_email: campaign['Allow SMTP Email'] || campaign.allow_smtp_email,
          allow_mailto_link: campaign['Allow Mailto Link'] || campaign.allow_mailto_link,
          collect_user_info: campaign['Collect User Info'] || campaign.collect_user_info,
          show_email_count: campaign['Show Email Count'] || campaign.show_email_count,
          allow_email_editing: campaign['Allow Email Editing'] || campaign.allow_email_editing,
          target_government_levels: normalizeTargetLevels(campaign['Target Government Levels'] || campaign.target_government_levels),
          created_at: campaign.CreatedAt || campaign.created_at,
          updated_at: campaign.UpdatedAt || campaign.updated_at,
          created_by_user_id: campaign['Created By User ID'] || campaign.created_by_user_id || null,
          created_by_user_email: campaign['Created By User Email'] || campaign.created_by_user_email || null,
          created_by_user_name: campaign['Created By User Name'] || campaign.created_by_user_name || null,
          emailCount
        }
      });
    } catch (error) {
      console.error('Get campaign error:', error);
      res.status(500).json({
        success: false,
        error: 'Failed to retrieve campaign',
        message: error.message,
        details: error.response?.data || null
      });
    }
  }

  // Get campaign by slug (for public access)
  async getCampaignBySlug(req, res, next) {
    try {
      const { slug } = req.params;
      const campaign = await nocoDB.getCampaignBySlug(slug);
      
      if (!campaign) {
        return res.status(404).json({
          success: false,
          error: 'Campaign not found'
        });
      }

  const campaignStatus = normalizeStatus(campaign['Status'] || campaign.status);
  if (campaignStatus !== 'active') {
        return res.status(403).json({
          success: false,
          error: 'Campaign is not currently active'
        });
      }

      // Get email count if enabled
      let emailCount = null;
      const showEmailCount = campaign['Show Email Count'] || campaign.show_email_count;
      if (showEmailCount) {
        const id = campaign.ID || campaign.Id || campaign.id;
        console.log('Getting email count for campaign ID:', id);
        if (id != null) {
          emailCount = await nocoDB.getCampaignEmailCount(id);
          console.log('Email count result:', emailCount);
        }
      }

      // Get call count if enabled
      let callCount = null;
      const showCallCount = campaign['Show Call Count'] || campaign.show_call_count;
      if (showCallCount) {
        const id = campaign.ID || campaign.Id || campaign.id;
        console.log('Getting call count for campaign ID:', id);
        if (id != null) {
          callCount = await nocoDB.getCampaignCallCount(id);
          console.log('Call count result:', callCount);
        }
      }

      // Debug cover photo value
      const coverPhoto = campaign['Cover Photo'] || campaign.cover_photo;
      console.log('Raw cover_photo from NocoDB:', coverPhoto, 'Type:', typeof coverPhoto);

      res.json({
        success: true,
        campaign: {
          id: campaign.ID || campaign.Id || campaign.id,
          slug: campaign['Campaign Slug'] || campaign.slug,
          title: campaign['Campaign Title'] || campaign.title,
          description: campaign['Description'] || campaign.description,
          call_to_action: campaign['Call to Action'] || campaign.call_to_action,
          cover_photo: coverPhoto || null,
          email_subject: campaign['Email Subject'] || campaign.email_subject,
          email_body: campaign['Email Body'] || campaign.email_body,
          allow_smtp_email: campaign['Allow SMTP Email'] || campaign.allow_smtp_email,
          allow_mailto_link: campaign['Allow Mailto Link'] || campaign.allow_mailto_link,
          collect_user_info: campaign['Collect User Info'] || campaign.collect_user_info,
          show_email_count: campaign['Show Email Count'] || campaign.show_email_count,
          show_call_count: campaign['Show Call Count'] || campaign.show_call_count,
          allow_email_editing: campaign['Allow Email Editing'] || campaign.allow_email_editing,
          target_government_levels: normalizeTargetLevels(campaign['Target Government Levels'] || campaign.target_government_levels),
          emailCount,
          callCount
        }
      });
    } catch (error) {
      console.error('Get campaign by slug error:', error);
      res.status(500).json({
        success: false,
        error: 'Failed to retrieve campaign',
        message: error.message,
        details: error.response?.data || null
      });
    }
  }

  // Create new campaign
  async createCampaign(req, res, next) {
    try {
      const {
        title,
        description,
        email_subject,
        email_body,
        call_to_action,
        status = 'draft',
        allow_smtp_email = true,
        allow_mailto_link = true,
        collect_user_info = true,
        show_email_count = true,
        allow_email_editing = false,
        target_government_levels = ['Federal', 'Provincial', 'Municipal']
      } = req.body;

      const ownerUserId = req.user?.id ?? req.session?.userId ?? null;
      const ownerEmail = req.user?.email ?? req.session?.userEmail ?? null;
      const ownerName = req.user?.name ?? req.session?.userName ?? null;
      const normalizedStatus = normalizeStatus(status, 'draft');
      let slug = generateSlug(title);
      
      // Ensure slug is unique
      let counter = 1;
      let originalSlug = slug;
      while (await nocoDB.getCampaignBySlug(slug)) {
        slug = `${originalSlug}-${counter}`;
        counter++;
      }

      const campaignData = {
        slug,
        title,
        description,
        email_subject,
        email_body,
        call_to_action,
        status: normalizedStatus,
        allow_smtp_email,
        allow_mailto_link,
        collect_user_info,
        show_email_count,
        allow_email_editing,
        // NocoDB MultiSelect expects an array of values
        target_government_levels: normalizeTargetLevels(target_government_levels),
        // Add user ownership data
        created_by_user_id: ownerUserId,
        created_by_user_email: ownerEmail,
        created_by_user_name: ownerName,
        // Add cover photo if uploaded
        cover_photo: req.file ? req.file.filename : null
      };

      const campaign = await nocoDB.createCampaign(campaignData);

      // Normalize the created campaign data
      res.status(201).json({
        success: true,
        campaign: {
          id: campaign.ID || campaign.Id || campaign.id,
          slug: campaign['Campaign Slug'] || campaign.slug,
          title: campaign['Campaign Title'] || campaign.title,
          description: campaign['Description'] || campaign.description,
          email_subject: campaign['Email Subject'] || campaign.email_subject,
          email_body: campaign['Email Body'] || campaign.email_body,
          call_to_action: campaign['Call to Action'] || campaign.call_to_action,
          cover_photo: campaign['Cover Photo'] || campaign.cover_photo,
          status: normalizeStatus(campaign['Status'] || campaign.status),
          allow_smtp_email: campaign['Allow SMTP Email'] || campaign.allow_smtp_email,
          allow_mailto_link: campaign['Allow Mailto Link'] || campaign.allow_mailto_link,
          collect_user_info: campaign['Collect User Info'] || campaign.collect_user_info,
          show_email_count: campaign['Show Email Count'] || campaign.show_email_count,
          allow_email_editing: campaign['Allow Email Editing'] || campaign.allow_email_editing,
          target_government_levels: normalizeTargetLevels(campaign['Target Government Levels'] || campaign.target_government_levels),
          created_at: campaign.CreatedAt || campaign.created_at,
          updated_at: campaign.UpdatedAt || campaign.updated_at,
          created_by_user_id: campaign['Created By User ID'] || campaign.created_by_user_id || ownerUserId,
          created_by_user_email: campaign['Created By User Email'] || campaign.created_by_user_email || ownerEmail,
          created_by_user_name: campaign['Created By User Name'] || campaign.created_by_user_name || ownerName
        }
      });
    } catch (error) {
      console.error('Create campaign error:', error);
      res.status(500).json({
        success: false,
        error: 'Failed to create campaign',
        message: error.message,
        details: error.response?.data || null
      });
    }
  }

  // Update campaign
  async updateCampaign(req, res, next) {
    try {
      const { id } = req.params;
      const updates = { ...req.body };

      const existingCampaign = await nocoDB.getCampaignById(id);
      if (!existingCampaign) {
        return res.status(404).json({
          success: false,
          error: 'Campaign not found'
        });
      }

      const isAdmin = (req.user && req.user.isAdmin) || req.session?.isAdmin || false;
      const sessionUserId = req.user?.id ?? req.session?.userId ?? null;
      const sessionUserEmail = req.user?.email ?? req.session?.userEmail ?? null;

      if (!isAdmin) {
        const createdById = existingCampaign['Created By User ID'] ?? existingCampaign.created_by_user_id ?? null;
        const createdByEmail = existingCampaign['Created By User Email'] ?? existingCampaign.created_by_user_email ?? null;

        const ownsCampaign = (
          (createdById != null && sessionUserId != null && String(createdById) === String(sessionUserId)) ||
          (createdByEmail && sessionUserEmail && String(createdByEmail).toLowerCase() === String(sessionUserEmail).toLowerCase())
        );

        if (!ownsCampaign) {
          return res.status(403).json({
            success: false,
            error: 'Access denied'
          });
        }
      }

      // Track old slug for cascade updates
      const oldSlug = existingCampaign['Campaign Slug'] || existingCampaign.slug;
      let newSlug = oldSlug;

      if (updates.title) {
        let slug = generateSlug(updates.title);

        const campaignWithSlug = await nocoDB.getCampaignBySlug(slug);
        const existingId = campaignWithSlug ? (campaignWithSlug.ID || campaignWithSlug.Id || campaignWithSlug.id) : null;
        if (campaignWithSlug && String(existingId) !== String(id)) {
          let counter = 1;
          const originalSlug = slug;
          while (await nocoDB.getCampaignBySlug(slug)) {
            slug = `${originalSlug}-${counter}`;
            counter++;
          }
        }
        updates.slug = slug;
        newSlug = slug;
      }

      if (updates.target_government_levels !== undefined) {
        updates.target_government_levels = normalizeTargetLevels(updates.target_government_levels);
      }

      // Handle cover photo upload
      if (req.file) {
        console.log('Cover photo file received:', req.file.filename);
        updates.cover_photo = req.file.filename;
      } else {
        console.log('No cover photo file in request');
      }
      
      console.log('Updates object before saving:', updates);

      if (updates.status !== undefined) {
        const sanitizedStatus = normalizeStatus(updates.status, null);
        if (!sanitizedStatus) {
          return res.status(400).json({
            success: false,
            error: 'Invalid campaign status'
          });
        }
        updates.status = sanitizedStatus;
      }

      // Remove user ownership fields from updates to prevent unauthorized changes
      delete updates.created_by_user_id;
      delete updates.created_by_user_email;
      delete updates.created_by_user_name;
      // Remove auto-generated fields that NocoDB handles
      delete updates.updated_at;
      delete updates.UpdatedAt;
      delete updates.created_at;
      delete updates.CreatedAt;

      const campaign = await nocoDB.updateCampaign(id, updates);

      // If slug changed, update references in related tables
      if (oldSlug && newSlug && oldSlug !== newSlug) {
        console.log(`Campaign slug changed from '${oldSlug}' to '${newSlug}', updating references...`);
        const cascadeResult = await nocoDB.updateCampaignSlugReferences(id, oldSlug, newSlug);
        
        if (cascadeResult.success) {
          console.log(`Successfully updated slug references: ${cascadeResult.updatedCampaignEmails} campaign emails, ${cascadeResult.updatedCallLogs} call logs`);
        } else {
          console.warn(`Failed to update some slug references:`, cascadeResult.error);
          // Don't fail the main update - cascade is a best-effort operation
        }
      }

      res.json({
        success: true,
        campaign: {
          id: campaign.ID || campaign.Id || campaign.id,
          slug: campaign['Campaign Slug'] || campaign.slug,
          title: campaign['Campaign Title'] || campaign.title,
          description: campaign['Description'] || campaign.description,
          email_subject: campaign['Email Subject'] || campaign.email_subject,
          email_body: campaign['Email Body'] || campaign.email_body,
          call_to_action: campaign['Call to Action'] || campaign.call_to_action,
          cover_photo: campaign['Cover Photo'] || campaign.cover_photo,
          status: normalizeStatus(campaign['Status'] || campaign.status),
          allow_smtp_email: campaign['Allow SMTP Email'] || campaign.allow_smtp_email,
          allow_mailto_link: campaign['Allow Mailto Link'] || campaign.allow_mailto_link,
          collect_user_info: campaign['Collect User Info'] || campaign.collect_user_info,
          show_email_count: campaign['Show Email Count'] || campaign.show_email_count,
          allow_email_editing: campaign['Allow Email Editing'] || campaign.allow_email_editing,
          target_government_levels: normalizeTargetLevels(campaign['Target Government Levels'] || campaign.target_government_levels),
          created_at: campaign.CreatedAt || campaign.created_at,
          updated_at: campaign.UpdatedAt || campaign.updated_at,
          created_by_user_id: campaign['Created By User ID'] || campaign.created_by_user_id || null,
          created_by_user_email: campaign['Created By User Email'] || campaign.created_by_user_email || null,
          created_by_user_name: campaign['Created By User Name'] || campaign.created_by_user_name || null
        }
      });
    } catch (error) {
      console.error('Update campaign error:', error);
      res.status(500).json({
        success: false,
        error: 'Failed to update campaign',
        message: error.message,
        details: error.response?.data || null
      });
    }
  }

  // Delete campaign
  async deleteCampaign(req, res, next) {
    try {
      const { id } = req.params;
      
      await nocoDB.deleteCampaign(id);

      res.json({
        success: true,
        message: 'Campaign deleted successfully'
      });
    } catch (error) {
      console.error('Delete campaign error:', error);
      res.status(500).json({
        success: false,
        error: 'Failed to delete campaign',
        message: error.message,
        details: error.response?.data || null
      });
    }
  }

  // Send campaign email
  async sendCampaignEmail(req, res, next) {
    try {
      const { slug } = req.params;
      const {
        userEmail,
        userName,
        postalCode,
        recipientEmail,
        recipientName,
        recipientTitle,
        recipientLevel,
        emailMethod = 'smtp',
        customEmailSubject,
        customEmailBody
      } = req.body;

      // Get campaign
      const campaign = await nocoDB.getCampaignBySlug(slug);
      if (!campaign) {
        return res.status(404).json({
          success: false,
          error: 'Campaign not found'
        });
      }

      const campaignStatus = normalizeStatus(campaign['Status'] || campaign.status);
      if (campaignStatus !== 'active') {
        return res.status(403).json({
          success: false,
          error: 'Campaign is not currently active'
        });
      }

      // Check if the requested email method is allowed
      if (emailMethod === 'smtp' && !(campaign['Allow SMTP Email'] || campaign.allow_smtp_email)) {
        return res.status(403).json({
          success: false,
          error: 'SMTP email sending is not enabled for this campaign'
        });
      }

      if (emailMethod === 'mailto' && !(campaign['Allow Mailto Link'] || campaign.allow_mailto_link)) {
        return res.status(403).json({
          success: false,
          error: 'Mailto links are not enabled for this campaign'
        });
      }

    // Use custom email content if provided (when email editing is enabled), otherwise use campaign defaults
    const allowEmailEditing = campaign['Allow Email Editing'] || campaign.allow_email_editing;
      const subject = (allowEmailEditing && customEmailSubject) 
        ? customEmailSubject 
        : (campaign['Email Subject'] || campaign.email_subject);
      const message = (allowEmailEditing && customEmailBody) 
        ? customEmailBody 
        : (campaign['Email Body'] || campaign.email_body);

      let emailResult = { success: true };

      // Send email if SMTP method
      if (emailMethod === 'smtp') {
        console.log('DEBUG: About to send campaign email...');
        emailResult = await emailService.sendCampaignEmail(
          recipientEmail,
          userEmail,
          userName || 'A constituent',
          postalCode,
          subject,
          message,
          campaign['Campaign Title'] || campaign.title,
          recipientName,
          recipientLevel
        );
        console.log('DEBUG: Campaign email service returned:', emailResult);
      }

      // Log the campaign email
      console.log('DEBUG: About to log campaign email with emailResult:', emailResult);
      await nocoDB.logCampaignEmail({
        campaign_id: campaign.ID || campaign.Id || campaign.id,
        campaign_slug: slug,
        user_email: userEmail,
        user_name: userName,
        user_postal_code: postalCode,
        recipient_email: recipientEmail,
        recipient_name: recipientName,
        recipient_title: recipientTitle,
        recipient_level: recipientLevel,
        email_method: emailMethod,
        subject: subject,
        message: message,
        status: emailMethod === 'mailto' ? 'clicked' : (emailResult.success ? 'sent' : 'failed')
      });
      console.log('DEBUG: Campaign email logged with status:', emailMethod === 'mailto' ? 'clicked' : (emailResult.success ? 'sent' : 'failed'));

      if (emailMethod === 'smtp') {
        if (emailResult.success) {
          res.json({
            success: true,
            message: 'Email sent successfully'
          });
        } else {
          res.status(500).json({
            success: false,
            error: 'Failed to send email',
            message: emailResult.error
          });
        }
      } else {
        // For mailto, just return success since we're tracking the click
        res.json({
          success: true,
          message: 'Email action tracked'
        });
      }

    } catch (error) {
      console.error('Send campaign email error:', error);
      res.status(500).json({
        success: false,
        error: 'Failed to process campaign email',
        message: error.message,
        details: error.response?.data || null
      });
    }
  }

  // Track user info when they find representatives
  async trackUserInfo(req, res, next) {
    try {
      const { slug } = req.params;
      const { userEmail, userName, postalCode } = req.body;

      // Get campaign
      const campaign = await nocoDB.getCampaignBySlug(slug);
      if (!campaign) {
        return res.status(404).json({
          success: false,
          error: 'Campaign not found'
        });
      }

      const campaignStatus = normalizeStatus(campaign['Status'] || campaign.status);
      if (campaignStatus !== 'active') {
        return res.status(403).json({
          success: false,
          error: 'Campaign is not currently active'
        });
      }

      // Log user interaction - finding representatives
      await nocoDB.logCampaignEmail({
        campaign_id: campaign.ID || campaign.Id || campaign.id,
        campaign_slug: slug,
        user_email: userEmail || '',
        user_name: userName || '',
        user_postal_code: postalCode,
        recipient_email: '',
        recipient_name: '',
        recipient_title: '',
        recipient_level: 'Other',
        email_method: 'smtp', // Use valid option but distinguish by status
        subject: 'User Info Capture',
        message: 'User searched for representatives',
        status: 'user_info_captured'
      });

      res.json({
        success: true,
        message: 'User info tracked successfully'
      });

    } catch (error) {
      console.error('Track user info error:', error);
      res.status(500).json({
        success: false,
        error: 'Failed to track user info',
        message: error.message,
        details: error.response?.data || null
      });
    }
  }

  // Get representatives for postal code (for campaign use)
  async getRepresentativesForCampaign(req, res, next) {
    try {
      const { slug, postalCode } = req.params;
      
      // Get campaign to check target levels
      const campaign = await nocoDB.getCampaignBySlug(slug);
      if (!campaign) {
        return res.status(404).json({
          success: false,
          error: 'Campaign not found'
        });
      }

      const campaignStatus = normalizeStatus(campaign['Status'] || campaign.status);
      if (campaignStatus !== 'active') {
        return res.status(403).json({
          success: false,
          error: 'Campaign is not currently active'
        });
      }

      // First check cache for representatives
      const formattedPostalCode = postalCode.replace(/\s/g, '').toUpperCase();
      let representatives = [];
      let result = null;
      
      // Try to check cached data first, but don't fail if NocoDB is down
      let cachedData = [];
      try {
        cachedData = await nocoDB.getRepresentativesByPostalCode(formattedPostalCode);
        console.log(`Cache check for ${formattedPostalCode}: found ${cachedData.length} records`);
        
        if (cachedData && cachedData.length > 0) {
          representatives = cachedData;
          console.log(`Using cached representatives for ${formattedPostalCode}`);
        }
      } catch (cacheError) {
        console.log(`Cache unavailable for ${formattedPostalCode}, proceeding with API call:`, cacheError.message);
      }

      // If not in cache, fetch from Represent API
      if (representatives.length === 0) {
        console.log(`Fetching representatives from Represent API for ${formattedPostalCode}`);
        result = await representAPI.getRepresentativesByPostalCode(postalCode);
        
        // Process representatives from both concordance and centroid
        // Add concordance representatives (if any)
        if (result.representatives_concordance && result.representatives_concordance.length > 0) {
          representatives = representatives.concat(result.representatives_concordance);
        }
        
        // Add centroid representatives (if any) - these are the actual elected officials
        if (result.representatives_centroid && result.representatives_centroid.length > 0) {
          representatives = representatives.concat(result.representatives_centroid);
        }

        // Cache the results if we got them from the API
        if (representatives.length > 0 && result) {
          console.log(`Attempting to cache ${representatives.length} representatives for ${formattedPostalCode}`);
          await cacheRepresentatives(formattedPostalCode, representatives, result);
        }
      }

      if (representatives.length === 0) {
        return res.json({
          success: false,
          message: 'No representatives found for this postal code',
          representatives: [],
          location: {
            city: result?.city || 'Alberta',
            province: result?.province || 'AB'
          }
        });
      }

      // Filter representatives by target government levels
      const targetGovernmentLevels = campaign['Target Government Levels'] || campaign.target_government_levels;
      const targetLevels = Array.isArray(targetGovernmentLevels)
        ? targetGovernmentLevels
        : (typeof targetGovernmentLevels === 'string' && targetGovernmentLevels.length > 0
          ? targetGovernmentLevels.split(',').map(level => level.trim())
          : ['Federal', 'Provincial', 'Municipal']);

      const filteredRepresentatives = representatives.filter(rep => {
        const repLevel = rep.elected_office ? rep.elected_office.toLowerCase() : 'other';
        
        return targetLevels.some(targetLevel => {
          const target = targetLevel.toLowerCase();
          
          if (target === 'federal' && (repLevel.includes('mp') || repLevel.includes('member of parliament'))) {
            return true;
          }
          if (target === 'provincial' && (repLevel.includes('mla') || repLevel.includes('legislative assembly'))) {
            return true;
          }
          if (target === 'municipal' && (repLevel.includes('mayor') || repLevel.includes('councillor') || repLevel.includes('council'))) {
            return true;
          }
          if (target === 'school board' && repLevel.includes('school')) {
            return true;
          }
          
          return false;
        });
      });

      res.json({
        success: true,
        representatives: filteredRepresentatives,
        location: {
          city: result?.city || cachedData[0]?.city || 'Alberta',
          province: result?.province || cachedData[0]?.province || 'AB'
        }
      });

    } catch (error) {
      console.error('Get representatives for campaign error:', error);
      res.status(500).json({
        success: false,
        error: 'Failed to get representatives',
        message: error.message,
        details: error.response?.data || null
      });
    }
  }

  // Get campaign analytics
  async getCampaignAnalytics(req, res, next) {
    try {
      const { id } = req.params;

      const campaign = await nocoDB.getCampaignById(id);

      if (!campaign) {
        return res.status(404).json({
          success: false,
          error: 'Campaign not found'
        });
      }

      const sessionUserId = req.user?.id ?? req.session?.userId ?? null;
      const sessionUserEmail = req.user?.email ?? req.session?.userEmail ?? null;
      const isAdmin = (req.user && req.user.isAdmin) || req.session?.isAdmin || false;

      if (!isAdmin) {
        const createdById = campaign['Created By User ID'] ?? campaign.created_by_user_id ?? null;
        const createdByEmail = campaign['Created By User Email'] ?? campaign.created_by_user_email ?? null;

        const ownsCampaign = (
          (createdById != null && sessionUserId != null && String(createdById) === String(sessionUserId)) ||
          (createdByEmail && sessionUserEmail && String(createdByEmail).toLowerCase() === String(sessionUserEmail).toLowerCase())
        );

        if (!ownsCampaign) {
          return res.status(403).json({
            success: false,
            error: 'Access denied'
          });
        }
      }
      
      const analytics = await nocoDB.getCampaignAnalytics(id);
      
      res.json({
        success: true,
        analytics
      });
    } catch (error) {
      console.error('Get campaign analytics error:', error);
      res.status(500).json({
        success: false,
        error: 'Failed to get campaign analytics',
        message: error.message,
        details: error.response?.data || null
      });
    }
  }

  // Track campaign phone call
  async trackCampaignCall(req, res, next) {
    try {
      const { slug } = req.params;
      const {
        representativeName,
        representativeTitle,
        phoneNumber,
        officeType,
        userEmail,
        userName,
        postalCode
      } = req.body;

      // Validate required fields
      if (!representativeName || !phoneNumber) {
        return res.status(400).json({
          success: false,
          error: 'Representative name and phone number are required'
        });
      }

      // Get campaign
      const campaign = await nocoDB.getCampaignBySlug(slug);
      if (!campaign) {
        return res.status(404).json({
          success: false,
          error: 'Campaign not found'
        });
      }

      const campaignStatus = normalizeStatus(campaign['Status'] || campaign.status);
      if (campaignStatus !== 'active') {
        return res.status(403).json({
          success: false,
          error: 'Campaign is not currently active'
        });
      }

      // Log the call
      await nocoDB.logCall({
        representativeName,
        representativeTitle: representativeTitle || null,
        phoneNumber,
        officeType: officeType || null,
        callerName: userName || null,
        callerEmail: userEmail || null,
        postalCode: postalCode || null,
        campaignId: campaign.ID || campaign.Id || campaign.id,
        campaignSlug: slug,
        callerIP: req.ip || req.connection?.remoteAddress || null,
        timestamp: new Date().toISOString()
      });

      res.json({
        success: true,
        message: 'Call tracked successfully'
      });
    } catch (error) {
      console.error('Track campaign call error:', error);
      res.status(500).json({
        success: false,
        error: 'Failed to track call',
        message: error.message
      });
    }
  }
}

// Export controller instance and upload middleware
const controller = new CampaignsController();
controller.upload = upload;

module.exports = controller;