// High-level payment-related email senders and payment config resolution.

import { db, dbGet, dbAll, events, tickets, payments, paymentOptions, eventPaymentOverrides } from '../../db/index.js';
import { eq } from 'drizzle-orm';
import { sendTemplateEmail } from './templateService.js';
import { formatDate, formatTime, formatCurrency, getSiteTimezone } from './formatting.js';

/**
 * Send payment receipt email
 */
export async function sendPaymentReceipt(paymentId: string): Promise<{ success: boolean; error?: string }> {
  // Get payment with ticket and event info
  const payment = await dbGet<any>(
    (db as any)
      .select()
      .from(payments)
      .where(eq((payments as any).id, paymentId))
  );

  if (!payment) {
    return { success: false, error: 'Payment not found' };
  }

  const ticket = await dbGet<any>(
    (db as any)
      .select()
      .from(tickets)
      .where(eq((tickets as any).id, payment.ticketId))
  );

  if (!ticket) {
    return { success: false, error: 'Ticket not found' };
  }

  const event = await dbGet<any>(
    (db as any)
      .select()
      .from(events)
      .where(eq((events as any).id, ticket.eventId))
  );

  if (!event) {
    return { success: false, error: 'Event not found' };
  }

  // Calculate total amount for multi-ticket bookings
  let totalAmount = payment.amount;
  let ticketCount = 1;

  if (ticket.bookingId) {
    // Get all payments for this booking
    const bookingTickets = await dbAll<any>(
      (db as any)
        .select()
        .from(tickets)
        .where(eq((tickets as any).bookingId, ticket.bookingId))
    );

    ticketCount = bookingTickets.length;

    // Sum up all payment amounts for the booking
    const bookingPayments = await Promise.all(
      bookingTickets.map((t: any) =>
        dbGet<any>((db as any).select().from(payments).where(eq((payments as any).ticketId, t.id)))
      )
    );

    totalAmount = bookingPayments
      .filter((p: any) => p)
      .reduce((sum: number, p: any) => sum + Number(p.amount || 0), 0);
  }

  const locale = ticket.preferredLanguage || 'en';
  const eventTitle = locale === 'es' && event.titleEs ? event.titleEs : event.title;

  const paymentMethodNames: Record<string, Record<string, string>> = {
    en: { bancard: 'Card', lightning: 'Lightning (Bitcoin)', cash: 'Cash', bank_transfer: 'Bank Transfer', tpago: 'TPago' },
    es: { bancard: 'Tarjeta', lightning: 'Lightning (Bitcoin)', cash: 'Efectivo', bank_transfer: 'Transferencia Bancaria', tpago: 'TPago' },
  };

  const receiptFullName = `${ticket.attendeeFirstName} ${ticket.attendeeLastName || ''}`.trim();

  // Format amount with ticket count info for multi-ticket bookings
  const amountDisplay = ticketCount > 1
    ? `${formatCurrency(totalAmount, payment.currency)} (${ticketCount} tickets)`
    : formatCurrency(totalAmount, payment.currency);

  // Get site timezone for proper date/time formatting
  const timezone = await getSiteTimezone();

  return sendTemplateEmail({
    templateSlug: 'payment-receipt',
    to: ticket.attendeeEmail,
    toName: receiptFullName,
    locale,
    eventId: event.id,
    variables: {
      attendeeName: receiptFullName,
      ticketId: ticket.bookingId || ticket.id,
      eventTitle,
      eventDate: formatDate(event.startDatetime, locale, timezone),
      paymentAmount: amountDisplay,
      paymentMethod: paymentMethodNames[locale]?.[payment.provider] || payment.provider,
      paymentReference: payment.reference || payment.id,
      paymentDate: formatDate(payment.paidAt || payment.createdAt, locale, timezone),
    },
  });
}

/**
 * Get merged payment configuration for an event (global + overrides)
 */
export async function getPaymentConfig(eventId: string): Promise<Record<string, any>> {
  // Get global options
  const globalOptions = await dbGet<any>(
    (db as any)
      .select()
      .from(paymentOptions)
  );

  // Get event overrides
  const overrides = await dbGet<any>(
    (db as any)
      .select()
      .from(eventPaymentOverrides)
      .where(eq((eventPaymentOverrides as any).eventId, eventId))
  );

  // Defaults
  const defaults = {
    tpagoEnabled: false,
    tpagoLink: null,
    tpagoLink2: null,
    tpagoLink3: null,
    tpagoLink4: null,
    tpagoLink5: null,
    tpagoInstructions: null,
    tpagoInstructionsEs: null,
    bankTransferEnabled: false,
    bankName: null,
    bankAccountHolder: null,
    bankAccountNumber: null,
    bankAlias: null,
    bankPhone: null,
    bankNotes: null,
    bankNotesEs: null,
  };

  const global = globalOptions || defaults;

  // Merge: override values take precedence if they're not null/undefined
  return {
    tpagoEnabled: overrides?.tpagoEnabled ?? global.tpagoEnabled,
    tpagoLink: overrides?.tpagoLink ?? global.tpagoLink,
    tpagoLink2: overrides?.tpagoLink2 ?? global.tpagoLink2,
    tpagoLink3: overrides?.tpagoLink3 ?? global.tpagoLink3,
    tpagoLink4: overrides?.tpagoLink4 ?? global.tpagoLink4,
    tpagoLink5: overrides?.tpagoLink5 ?? global.tpagoLink5,
    tpagoInstructions: overrides?.tpagoInstructions ?? global.tpagoInstructions,
    tpagoInstructionsEs: overrides?.tpagoInstructionsEs ?? global.tpagoInstructionsEs,
    bankTransferEnabled: overrides?.bankTransferEnabled ?? global.bankTransferEnabled,
    bankName: overrides?.bankName ?? global.bankName,
    bankAccountHolder: overrides?.bankAccountHolder ?? global.bankAccountHolder,
    bankAccountNumber: overrides?.bankAccountNumber ?? global.bankAccountNumber,
    bankAlias: overrides?.bankAlias ?? global.bankAlias,
    bankPhone: overrides?.bankPhone ?? global.bankPhone,
    bankNotes: overrides?.bankNotes ?? global.bankNotes,
    bankNotesEs: overrides?.bankNotesEs ?? global.bankNotesEs,
  };
}

/**
 * Send payment instructions email (for TPago or Bank Transfer)
 * This email is sent immediately after user clicks "Continue to Payment"
 */
export async function sendPaymentInstructions(ticketId: string): Promise<{ success: boolean; error?: string }> {
  // Get ticket
  const ticket = await dbGet<any>(
    (db as any)
      .select()
      .from(tickets)
      .where(eq((tickets as any).id, ticketId))
  );

  if (!ticket) {
    return { success: false, error: 'Ticket not found' };
  }

  // Get event
  const event = await dbGet<any>(
    (db as any)
      .select()
      .from(events)
      .where(eq((events as any).id, ticket.eventId))
  );

  if (!event) {
    return { success: false, error: 'Event not found' };
  }

  // Get payment
  const payment = await dbGet<any>(
    (db as any)
      .select()
      .from(payments)
      .where(eq((payments as any).ticketId, ticketId))
  );

  if (!payment) {
    return { success: false, error: 'Payment not found' };
  }

  // Only send for manual payment methods
  if (!['bank_transfer', 'tpago'].includes(payment.provider)) {
    return { success: false, error: 'Payment instructions email only for bank_transfer or tpago' };
  }

  // Get merged payment config for this event
  const paymentConfig = await getPaymentConfig(event.id);

  const locale = ticket.preferredLanguage || 'en';
  const eventTitle = locale === 'es' && event.titleEs ? event.titleEs : event.title;
  const attendeeFullName = `${ticket.attendeeFirstName} ${ticket.attendeeLastName || ''}`.trim();

  // Calculate total price for multi-ticket bookings
  let totalPrice = event.price;
  let ticketCount = 1;

  if (ticket.bookingId) {
    // Count all tickets in this booking
    const bookingTickets = await dbAll<any>(
      (db as any)
        .select()
        .from(tickets)
        .where(eq((tickets as any).bookingId, ticket.bookingId))
    );
    ticketCount = bookingTickets.length;
    totalPrice = event.price * ticketCount;
  }

  // Generate a payment reference using booking ID or ticket ID
  const paymentReference = `SPG-${(ticket.bookingId || ticket.id).substring(0, 8).toUpperCase()}`;

  // Generate the booking URL for returning to payment page
  const frontendUrl = process.env.FRONTEND_URL || 'https://spanglish.com';
  const bookingUrl = `${frontendUrl}/booking/${ticket.id}?step=payment`;

  // Determine which template to use
  const templateSlug = payment.provider === 'tpago'
    ? 'payment-instructions-tpago'
    : 'payment-instructions-bank-transfer';

  // Format amount with ticket count info for multi-ticket bookings
  const amountDisplay = ticketCount > 1
    ? `${formatCurrency(totalPrice, event.currency)} (${ticketCount} tickets)`
    : formatCurrency(totalPrice, event.currency);

  // Get site timezone for proper date/time formatting
  const timezone = await getSiteTimezone();

  // Build variables based on payment method
  const variables: Record<string, any> = {
    attendeeName: attendeeFullName,
    attendeeEmail: ticket.attendeeEmail,
    ticketId: ticket.bookingId || ticket.id,
    eventTitle,
    eventDate: formatDate(event.startDatetime, locale, timezone),
    eventTime: formatTime(event.startDatetime, locale, timezone),
    eventLocation: event.location,
    eventLocationUrl: event.locationUrl || '',
    paymentAmount: amountDisplay,
    paymentReference,
    bookingUrl,
  };

  // Add payment-method specific variables
  if (payment.provider === 'tpago') {
    // Select the TPago link matching the number of tickets (1-5), falling back to the base link
    const tpagoLinkKey = ticketCount <= 1 ? 'tpagoLink' : `tpagoLink${Math.min(ticketCount, 5)}`;
    variables.tpagoLink = paymentConfig[tpagoLinkKey] || paymentConfig.tpagoLink || '';
  } else {
    // Bank transfer
    variables.bankName = paymentConfig.bankName || '';
    variables.bankAccountHolder = paymentConfig.bankAccountHolder || '';
    variables.bankAccountNumber = paymentConfig.bankAccountNumber || '';
    variables.bankAlias = paymentConfig.bankAlias || '';
    variables.bankPhone = paymentConfig.bankPhone || '';
  }

  console.log(`[Email] Sending payment instructions email (${payment.provider}) to ${ticket.attendeeEmail}`);

  return sendTemplateEmail({
    templateSlug,
    to: ticket.attendeeEmail,
    toName: attendeeFullName,
    locale,
    eventId: event.id,
    variables,
  });
}

/**
 * Send payment rejection email
 * This email is sent when admin rejects a TPago or Bank Transfer payment
 */
export async function sendPaymentRejectionEmail(paymentId: string): Promise<{ success: boolean; error?: string }> {
  // Get payment
  const payment = await dbGet<any>(
    (db as any)
      .select()
      .from(payments)
      .where(eq((payments as any).id, paymentId))
  );

  if (!payment) {
    return { success: false, error: 'Payment not found' };
  }

  // Get ticket
  const ticket = await dbGet<any>(
    (db as any)
      .select()
      .from(tickets)
      .where(eq((tickets as any).id, payment.ticketId))
  );

  if (!ticket) {
    return { success: false, error: 'Ticket not found' };
  }

  // Get event
  const event = await dbGet<any>(
    (db as any)
      .select()
      .from(events)
      .where(eq((events as any).id, ticket.eventId))
  );

  if (!event) {
    return { success: false, error: 'Event not found' };
  }

  const locale = ticket.preferredLanguage || 'en';
  const eventTitle = locale === 'es' && event.titleEs ? event.titleEs : event.title;
  const attendeeFullName = `${ticket.attendeeFirstName} ${ticket.attendeeLastName || ''}`.trim();

  // Generate a new booking URL for the event
  const frontendUrl = process.env.FRONTEND_URL || 'https://spanglish.com';
  const newBookingUrl = `${frontendUrl}/book/${event.id}`;

  // Get site timezone for proper date/time formatting
  const timezone = await getSiteTimezone();

  console.log(`[Email] Sending payment rejection email to ${ticket.attendeeEmail}`);

  return sendTemplateEmail({
    templateSlug: 'payment-rejected',
    to: ticket.attendeeEmail,
    toName: attendeeFullName,
    locale,
    eventId: event.id,
    variables: {
      attendeeName: attendeeFullName,
      attendeeEmail: ticket.attendeeEmail,
      ticketId: ticket.id,
      eventTitle,
      eventDate: formatDate(event.startDatetime, locale, timezone),
      eventTime: formatTime(event.startDatetime, locale, timezone),
      eventLocation: event.location,
      eventLocationUrl: event.locationUrl || '',
      newBookingUrl,
    },
  });
}

/**
 * Send payment reminder email
 * This email is sent when admin wants to remind attendee about pending payment
 */
export async function sendPaymentReminder(paymentId: string): Promise<{ success: boolean; error?: string }> {
  // Get payment
  const payment = await dbGet<any>(
    (db as any)
      .select()
      .from(payments)
      .where(eq((payments as any).id, paymentId))
  );

  if (!payment) {
    return { success: false, error: 'Payment not found' };
  }

  // Only send for pending/pending_approval payments
  if (!['pending', 'pending_approval'].includes(payment.status)) {
    return { success: false, error: 'Payment reminder can only be sent for pending payments' };
  }

  // Get ticket
  const ticket = await dbGet<any>(
    (db as any)
      .select()
      .from(tickets)
      .where(eq((tickets as any).id, payment.ticketId))
  );

  if (!ticket) {
    return { success: false, error: 'Ticket not found' };
  }

  // Get event
  const event = await dbGet<any>(
    (db as any)
      .select()
      .from(events)
      .where(eq((events as any).id, ticket.eventId))
  );

  if (!event) {
    return { success: false, error: 'Event not found' };
  }

  const locale = ticket.preferredLanguage || 'en';
  const eventTitle = locale === 'es' && event.titleEs ? event.titleEs : event.title;
  const attendeeFullName = `${ticket.attendeeFirstName} ${ticket.attendeeLastName || ''}`.trim();

  // Calculate total price for multi-ticket bookings
  let totalPrice = event.price;
  let ticketCount = 1;

  if (ticket.bookingId) {
    const bookingTickets = await dbAll<any>(
      (db as any)
        .select()
        .from(tickets)
        .where(eq((tickets as any).bookingId, ticket.bookingId))
    );
    ticketCount = bookingTickets.length;
    totalPrice = event.price * ticketCount;
  }

  // Generate the booking URL for returning to payment page
  const frontendUrl = process.env.FRONTEND_URL || 'https://spanglish.com';
  const bookingUrl = `${frontendUrl}/booking/${ticket.id}?step=payment`;

  // Format amount with ticket count info for multi-ticket bookings
  const amountDisplay = ticketCount > 1
    ? `${formatCurrency(totalPrice, event.currency)} (${ticketCount} tickets)`
    : formatCurrency(totalPrice, event.currency);

  // Get site timezone for proper date/time formatting
  const timezone = await getSiteTimezone();

  console.log(`[Email] Sending payment reminder email to ${ticket.attendeeEmail}`);

  return sendTemplateEmail({
    templateSlug: 'payment-reminder',
    to: ticket.attendeeEmail,
    toName: attendeeFullName,
    locale,
    eventId: event.id,
    variables: {
      attendeeName: attendeeFullName,
      attendeeEmail: ticket.attendeeEmail,
      ticketId: ticket.bookingId || ticket.id,
      eventTitle,
      eventDate: formatDate(event.startDatetime, locale, timezone),
      eventTime: formatTime(event.startDatetime, locale, timezone),
      eventLocation: event.location,
      eventLocationUrl: event.locationUrl || '',
      paymentAmount: amountDisplay,
      bookingUrl,
    },
  });
}
