// Application form API endpoint
// Handles full event applications with PostgreSQL storage and Mailcow SMTP emails

const { Pool } = require('pg');
const nodemailer = require('nodemailer');
const { syncApplication } = require('./google-sheets');
const { createPayment, TICKET_LABELS, REGISTRATION_PRICING, ACCOMMODATION_PRICES, ACCOMMODATION_LABELS, PROCESSING_FEE_PERCENT, calculateAmount, getPricingTier } = require('./mollie');
const { addToListmonk } = require('./listmonk');

// Initialize PostgreSQL connection pool
const pool = new Pool({
  connectionString: process.env.DATABASE_URL,
  ssl: process.env.DATABASE_SSL === 'true' ? { rejectUnauthorized: false } : false
});

// Initialize SMTP transport (Mailcow)
const smtp = nodemailer.createTransport({
  host: process.env.SMTP_HOST || 'mail.rmail.online',
  port: parseInt(process.env.SMTP_PORT || '587'),
  secure: false,
  auth: {
    user: process.env.SMTP_USER || 'contact@valleyofthecommons.com',
    pass: process.env.SMTP_PASS || '',
  },
  tls: { rejectUnauthorized: false },
});

// Week labels for email display
const WEEK_LABELS = {
  week1: 'Week 1: Return to the Commons (Aug 24-30)',
  week2: 'Week 2: Post-Capitalist Production (Aug 31-Sep 6)',
  week3: 'Week 3: Future Living (Sep 7-13)',
  week4: 'Week 4: Governance & Funding Models (Sep 14-20)',
};

// Email templates
const confirmationEmail = (application) => {
  const weeksCount = (application.weeks || []).length;
  const accomType = application.accommodation_type || null;
  const pricing = calculateAmount('registration', weeksCount, accomType);
  const weeksHtml = (application.weeks || []).map(w => `<li>${WEEK_LABELS[w] || w}</li>`).join('');

  // Accommodation row
  let accomHtml = '';
  if (accomType && ACCOMMODATION_PRICES[accomType]) {
    const label = ACCOMMODATION_LABELS[accomType] || accomType;
    const accomPrices = ACCOMMODATION_PRICES[accomType];
    const accomDisplay = weeksCount === 4
      ? `${label} — &euro;${accomPrices.perMonth} (full month)`
      : `${label} — &euro;${accomPrices.perWeek}/week &times; ${weeksCount} week${weeksCount > 1 ? 's' : ''} = &euro;${pricing.accommodation}`;
    accomHtml = `
          <tr>
            <td style="padding: 6px 0; border-bottom: 1px solid #e0e0e0;"><strong>Accommodation:</strong></td>
            <td style="padding: 6px 0; border-bottom: 1px solid #e0e0e0;">${accomDisplay}</td>
          </tr>`;
  }

  // Food note
  const foodNote = application.want_food
    ? '<tr><td style="padding: 6px 0; border-bottom: 1px solid #e0e0e0;"><strong>Food:</strong></td><td style="padding: 6px 0; border-bottom: 1px solid #e0e0e0;">Interest registered — we are exploring co-producing meals as a community. More details and costs coming soon.</td></tr>'
    : '';

  return {
    subject: 'Welcome to the Process - Valley of the Commons',
    html: `
    <div style="font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; max-width: 600px; margin: 0 auto; padding: 20px;">
      <h1 style="color: #2d5016; margin-bottom: 24px;">We're glad you're here, ${application.first_name}!</h1>

      <p>Your application to <strong>Valley of the Commons</strong> (August 24 – September 20, 2026) has been received. We're excited to read about what you'll bring to the village.</p>

      <div style="background: #f5f5f0; padding: 20px; border-radius: 8px; margin: 24px 0;">
        <h3 style="margin-top: 0; color: #2d5016;">Your Booking Summary</h3>
        <table style="width: 100%; border-collapse: collapse;">
          <tr>
            <td style="padding: 6px 0; border-bottom: 1px solid #e0e0e0;"><strong>Registration:</strong></td>
            <td style="padding: 6px 0; border-bottom: 1px solid #e0e0e0;">${weeksCount === 4 ? `&euro;${pricing.registration} (full month)` : `&euro;${REGISTRATION_PRICING[pricing.tier].perWeek}/week &times; ${weeksCount} week${weeksCount > 1 ? 's' : ''} = &euro;${pricing.registration}`} (${pricing.tier === 'early' ? 'Early Bird' : pricing.tier === 'standard' ? 'Standard' : 'Last Minute'} rate)</td>
          </tr>
          ${accomHtml}
          <tr>
            <td style="padding: 6px 0; border-bottom: 1px solid #e0e0e0;"><strong>Processing fee (2%):</strong></td>
            <td style="padding: 6px 0; border-bottom: 1px solid #e0e0e0;">&euro;${pricing.processingFee}</td>
          </tr>
          <tr>
            <td style="padding: 6px 0; border-bottom: 1px solid #e0e0e0;"><strong>Total:</strong></td>
            <td style="padding: 6px 0; border-bottom: 1px solid #e0e0e0;"><strong>&euro;${pricing.total}</strong></td>
          </tr>
          <tr>
            <td style="padding: 6px 0; border-bottom: 1px solid #e0e0e0;"><strong>Attendance:</strong></td>
            <td style="padding: 6px 0; border-bottom: 1px solid #e0e0e0;">${application.attendance_type === 'full' ? 'Full 4 weeks' : 'Partial'}</td>
          </tr>
          ${foodNote}
        </table>
        ${weeksHtml ? `<p style="margin-top: 12px; margin-bottom: 0;"><strong>Weeks selected:</strong></p><ul style="margin-top: 4px; margin-bottom: 0;">${weeksHtml}</ul>` : ''}
      </div>

      <div style="background: #f5f5f0; padding: 20px; border-radius: 8px; margin: 24px 0;">
        <h3 style="margin-top: 0; color: #2d5016;">What happens next?</h3>
        <ol style="margin-bottom: 0;">
          <li><a href="${process.env.BASE_URL || 'https://valleyofthecommons.com'}/api/mollie/resume?id=${application.id}" style="color: #2d5016; font-weight: 600;">Complete your registration payment</a> (if you haven't already)</li>
          <li>Our team will review your application within <strong>1 week</strong></li>
          <li>We may reach out with follow-up questions</li>
          ${accomType ? '<li>Your accommodation will be allocated and details sent to you shortly after payment is confirmed</li>' : ''}
        </ol>
      </div>

      <p>In the meantime, feel free to explore more about the Commons Hub and our community:</p>
      <ul>
        <li><a href="https://www.commons-hub.at/">Commons Hub Website</a></li>
        <li><a href="https://valleyofthecommons.com/">Valley of the Commons</a></li>
      </ul>

      <p>If you have any questions, just reply to this email — we'd love to hear from you.</p>

      <p style="margin-top: 32px;">
        With warmth,<br>
        <strong>The Valley of the Commons Team</strong>
      </p>

      <hr style="border: none; border-top: 1px solid #ddd; margin: 32px 0;">
      <p style="font-size: 12px; color: #666;">
        Application ID: ${application.id}<br>
        Submitted: ${new Date(application.submitted_at).toLocaleDateString('en-US', { dateStyle: 'long' })}
      </p>
    </div>
  `
  };
};

const adminNotificationEmail = (application) => ({
  subject: `New Application: ${application.first_name} ${application.last_name}`,
  html: `
    <div style="font-family: -apple-system, BlinkMacSystemFont, 'Segoe UI', Roboto, sans-serif; max-width: 600px; margin: 0 auto; padding: 20px;">
      <h2 style="color: #2d5016;">New Application Received</h2>

      <table style="width: 100%; border-collapse: collapse;">
        <tr>
          <td style="padding: 8px 0; border-bottom: 1px solid #eee;"><strong>Name:</strong></td>
          <td style="padding: 8px 0; border-bottom: 1px solid #eee;">${application.first_name} ${application.last_name}</td>
        </tr>
        <tr>
          <td style="padding: 8px 0; border-bottom: 1px solid #eee;"><strong>Email:</strong></td>
          <td style="padding: 8px 0; border-bottom: 1px solid #eee;"><a href="mailto:${application.email}">${application.email}</a></td>
        </tr>
        <tr>
          <td style="padding: 8px 0; border-bottom: 1px solid #eee;"><strong>Location:</strong></td>
          <td style="padding: 8px 0; border-bottom: 1px solid #eee;">${application.city || ''}, ${application.country || ''}</td>
        </tr>
        <tr>
          <td style="padding: 8px 0; border-bottom: 1px solid #eee;"><strong>Attendance:</strong></td>
          <td style="padding: 8px 0; border-bottom: 1px solid #eee;">${application.attendance_type === 'full' ? 'Full 4 weeks' : 'Partial'}</td>
        </tr>
        <tr>
          <td style="padding: 8px 0; border-bottom: 1px solid #eee;"><strong>Accommodation:</strong></td>
          <td style="padding: 8px 0; border-bottom: 1px solid #eee;">${application.accommodation_type ? (ACCOMMODATION_LABELS[application.accommodation_type] || application.accommodation_type) : (application.need_accommodation ? 'Yes (no type selected)' : 'No')}</td>
        </tr>
        <tr>
          <td style="padding: 8px 0; border-bottom: 1px solid #eee;"><strong>Food interest:</strong></td>
          <td style="padding: 8px 0; border-bottom: 1px solid #eee;">${application.want_food ? 'Yes — wants to co-produce meals' : 'No'}</td>
        </tr>
        <tr>
          <td style="padding: 8px 0; border-bottom: 1px solid #eee;"><strong>Scholarship:</strong></td>
          <td style="padding: 8px 0; border-bottom: 1px solid #eee;">${application.scholarship_needed ? 'Yes' : 'No'}</td>
        </tr>
      </table>

      <div style="background: #f5f5f0; padding: 16px; border-radius: 8px; margin: 24px 0;">
        <h3 style="margin-top: 0;">Motivation</h3>
        <p style="margin-bottom: 0; white-space: pre-wrap;">${application.motivation}</p>
      </div>

      <p>
        <a href="https://valleyofthecommons.com/admin.html" style="display: inline-block; background: #2d5016; color: white; padding: 12px 24px; text-decoration: none; border-radius: 6px;">
          Review Application
        </a>
      </p>

      <p style="font-size: 12px; color: #666; margin-top: 24px;">
        Application ID: ${application.id}
      </p>
    </div>
  `
});

async function logEmail(recipientEmail, recipientName, emailType, subject, messageId, metadata = {}) {
  try {
    await pool.query(
      `INSERT INTO email_log (recipient_email, recipient_name, email_type, subject, message_id, metadata)
       VALUES ($1, $2, $3, $4, $5, $6)`,
      [recipientEmail, recipientName, emailType, subject, messageId, JSON.stringify(metadata)]
    );
  } catch (error) {
    console.error('Failed to log email:', error);
  }
}

module.exports = async function handler(req, res) {
  // CORS headers
  res.setHeader('Access-Control-Allow-Origin', '*');
  res.setHeader('Access-Control-Allow-Methods', 'GET, POST, OPTIONS');
  res.setHeader('Access-Control-Allow-Headers', 'Content-Type, Authorization');

  if (req.method === 'OPTIONS') {
    return res.status(200).end();
  }

  // POST - Submit new application
  if (req.method === 'POST') {
    try {
      const data = req.body;

      // Validate required fields
      const required = ['first_name', 'last_name', 'email', 'motivation', 'belief_update', 'privacy_policy_accepted'];
      for (const field of required) {
        if (!data[field]) {
          return res.status(400).json({ error: `Missing required field: ${field}` });
        }
      }

      // Validate email format
      if (!data.email.includes('@')) {
        return res.status(400).json({ error: 'Invalid email address' });
      }

      // Check for duplicate application
      const existing = await pool.query(
        'SELECT id FROM applications WHERE email = $1',
        [data.email.toLowerCase().trim()]
      );

      if (existing.rows.length > 0) {
        return res.status(409).json({
          error: 'An application with this email already exists',
          applicationId: existing.rows[0].id
        });
      }

      // Prepare arrays for PostgreSQL
      const skills = Array.isArray(data.skills) ? data.skills : (data.skills ? [data.skills] : null);
      const languages = Array.isArray(data.languages) ? data.languages : (data.languages ? [data.languages] : null);
      const dietary = Array.isArray(data.dietary_requirements) ? data.dietary_requirements : (data.dietary_requirements ? [data.dietary_requirements] : null);
      const governance = Array.isArray(data.governance_interest) ? data.governance_interest : (data.governance_interest ? [data.governance_interest] : null);
      const previousEvents = Array.isArray(data.previous_events) ? data.previous_events : (data.previous_events ? [data.previous_events] : null);

      // Prepare new array fields
      const selectedWeeks = Array.isArray(data.weeks) ? data.weeks : (data.weeks ? [data.weeks] : []);
      const topThemes = Array.isArray(data.top_themes) ? data.top_themes : (data.top_themes ? [data.top_themes] : null);

      // Insert application
      const result = await pool.query(
        `INSERT INTO applications (
          first_name, last_name, email, phone, country, city, pronouns, date_of_birth,
          occupation, organization, skills, languages, website, social_links,
          attendance_type, arrival_date, departure_date, accommodation_preference,
          dietary_requirements, dietary_notes, motivation, contribution, projects,
          workshops_offer, commons_experience, community_experience, governance_interest,
          how_heard, referral_name, previous_events, emergency_name, emergency_phone,
          emergency_relationship, code_of_conduct_accepted, privacy_policy_accepted,
          photo_consent, scholarship_needed, scholarship_reason, contribution_amount,
          ip_address, user_agent, need_accommodation, want_food, accommodation_type,
          selected_weeks, top_themes, belief_update, volunteer_interest, coupon_code,
          food_preference, accessibility_needs
        ) VALUES (
          $1, $2, $3, $4, $5, $6, $7, $8, $9, $10, $11, $12, $13, $14, $15, $16, $17,
          $18, $19, $20, $21, $22, $23, $24, $25, $26, $27, $28, $29, $30, $31, $32,
          $33, $34, $35, $36, $37, $38, $39, $40, $41, $42, $43, $44,
          $45, $46, $47, $48, $49, $50, $51
        ) RETURNING id, submitted_at`,
        [
          data.first_name?.trim(),
          data.last_name?.trim(),
          data.email?.toLowerCase().trim(),
          data.phone?.trim() || null,
          data.country?.trim() || null,
          data.city?.trim() || null,
          data.pronouns?.trim() || null,
          data.date_of_birth || null,
          data.occupation?.trim() || null,
          data.organization?.trim() || null,
          skills,
          languages,
          data.website?.trim() || null,
          data.social_links ? JSON.stringify(data.social_links) : null,
          data.attendance_type || 'full',
          data.arrival_date || null,
          data.departure_date || null,
          data.accommodation_preference || null,
          dietary,
          data.dietary_notes?.trim() || null,
          data.motivation?.trim(),
          data.contribution?.trim() || null,
          data.projects?.trim() || null,
          data.workshops_offer?.trim() || null,
          data.commons_experience?.trim() || null,
          data.community_experience?.trim() || null,
          governance,
          data.how_heard?.trim() || null,
          data.referral_name?.trim() || null,
          previousEvents,
          data.emergency_name?.trim() || null,
          data.emergency_phone?.trim() || null,
          data.emergency_relationship?.trim() || null,
          data.code_of_conduct_accepted || false,
          data.privacy_policy_accepted || false,
          data.photo_consent || false,
          data.scholarship_needed || false,
          data.scholarship_reason?.trim() || null,
          'registration',
          req.headers['x-forwarded-for'] || req.connection?.remoteAddress || null,
          req.headers['user-agent'] || null,
          data.need_accommodation || false,
          data.want_food || false,
          data.accommodation_type || null,
          selectedWeeks.length > 0 ? selectedWeeks : null,
          topThemes,
          data.belief_update?.trim() || null,
          data.volunteer_interest || false,
          data.coupon_code?.trim() || null,
          data.food_preference?.trim() || null,
          data.accessibility_needs?.trim() || null
        ]
      );

      const application = {
        id: result.rows[0].id,
        submitted_at: result.rows[0].submitted_at,
        first_name: data.first_name,
        last_name: data.last_name,
        email: data.email,
        phone: data.phone,
        city: data.city,
        country: data.country,
        attendance_type: data.attendance_type,
        scholarship_needed: data.scholarship_needed,
        scholarship_reason: data.scholarship_reason,
        motivation: data.motivation,
        contribution: data.contribution,
        how_heard: data.how_heard,
        referral_name: data.referral_name,
        arrival_date: data.arrival_date,
        departure_date: data.departure_date,
        weeks: selectedWeeks,
        need_accommodation: data.need_accommodation || false,
        accommodation_preference: data.accommodation_preference || null,
        accommodation_type: data.accommodation_type || null,
        want_food: data.want_food || false,
        contribution_amount: 'registration',
      };

      // Sync to Google Sheets (fire-and-forget backup)
      syncApplication(application);

      // Add to Listmonk newsletter
      addToListmonk(application.email, `${application.first_name} ${application.last_name}`, {
        source: 'application',
        weeks: selectedWeeks,
        contributionAmount: data.contribution_amount,
      }).catch(err => console.error('[Listmonk] Application sync failed:', err.message));

      // Send confirmation email to applicant
      if (process.env.SMTP_PASS) {
        try {
          const confirmEmail = confirmationEmail(application);
          const info = await smtp.sendMail({
            from: process.env.EMAIL_FROM || 'Valley of the Commons <contact@valleyofthecommons.com>',
            to: application.email,
            bcc: 'team@valleyofthecommons.com',
            subject: confirmEmail.subject,
            html: confirmEmail.html,
          });
          await logEmail(application.email, `${application.first_name} ${application.last_name}`,
            'application_confirmation', confirmEmail.subject, info.messageId, { applicationId: application.id });
        } catch (emailError) {
          console.error('Failed to send confirmation email:', emailError);
        }

        // Send notification to admins
        try {
          const adminEmail = adminNotificationEmail(application);
          const adminRecipients = (process.env.ADMIN_EMAILS || 'jeff@jeffemmett.com').split(',');
          const info = await smtp.sendMail({
            from: process.env.EMAIL_FROM || 'Valley of the Commons <contact@valleyofthecommons.com>',
            to: adminRecipients.join(', '),
            subject: adminEmail.subject,
            html: adminEmail.html,
          });
          await logEmail(adminRecipients[0], 'Admin', 'admin_notification',
            adminEmail.subject, info.messageId, { applicationId: application.id });
        } catch (emailError) {
          console.error('Failed to send admin notification:', emailError);
        }
      }

      // Create Mollie payment for registration + accommodation fee
      let checkoutUrl = null;
      if (selectedWeeks.length > 0 && process.env.MOLLIE_API_KEY) {
        try {
          const paymentResult = await createPayment(
            application.id,
            'registration',
            selectedWeeks.length,
            application.email,
            application.first_name,
            application.last_name,
            application.accommodation_type,
            selectedWeeks
          );
          checkoutUrl = paymentResult.checkoutUrl;
          console.log(`Mollie payment created: ${paymentResult.paymentId} (€${paymentResult.amount})`);
        } catch (paymentError) {
          console.error('Failed to create Mollie payment:', paymentError);
          // Don't fail the application - payment can be retried
        }
      }

      return res.status(201).json({
        success: true,
        message: 'Application submitted successfully',
        applicationId: application.id,
        checkoutUrl,
      });

    } catch (error) {
      console.error('Application submission error:', error);
      return res.status(500).json({ error: 'Failed to submit application. Please try again.' });
    }
  }

  // GET - Retrieve applications (admin only)
  if (req.method === 'GET') {
    // Simple token-based auth for admin access
    const authHeader = req.headers.authorization;
    if (!authHeader || authHeader !== `Bearer ${process.env.ADMIN_API_KEY}`) {
      return res.status(401).json({ error: 'Unauthorized' });
    }

    try {
      const { status, limit = 50, offset = 0 } = req.query;

      let query = 'SELECT * FROM applications';
      const params = [];

      if (status) {
        query += ' WHERE status = $1';
        params.push(status);
      }

      query += ` ORDER BY submitted_at DESC LIMIT $${params.length + 1} OFFSET $${params.length + 2}`;
      params.push(parseInt(limit), parseInt(offset));

      const result = await pool.query(query, params);

      // Get total count
      let countQuery = 'SELECT COUNT(*) FROM applications';
      if (status) {
        countQuery += ' WHERE status = $1';
      }
      const countResult = await pool.query(countQuery, status ? [status] : []);

      return res.status(200).json({
        applications: result.rows,
        total: parseInt(countResult.rows[0].count),
        limit: parseInt(limit),
        offset: parseInt(offset)
      });

    } catch (error) {
      console.error('Failed to fetch applications:', error);
      return res.status(500).json({ error: 'Failed to fetch applications' });
    }
  }

  return res.status(405).json({ error: 'Method not allowed' });
};
