import { Worker, type Job } from 'bullmq';
import { env } from '@/lib/env';

import type { ConnectionOptions } from 'bullmq';
import { logger } from '@/lib/logger';
import { attachWorkerAudit } from '@/lib/queue/audit-helpers';
import { QUEUE_CONFIGS } from '@/lib/queue';

export const emailWorker = new Worker(
  'email',
  async (job: Job) => {
    logger.info({ jobId: job.id, jobName: job.name }, 'Processing email job');
    switch (job.name) {
      case 'inbox-sync': {
        const { accountId } = job.data as { accountId: string };
        const { syncInbox } = await import('@/lib/services/email-threads.service');
        await syncInbox(accountId);
        break;
      }
      case 'send-inquiry-confirmation': {
        const { to, firstName, mooringNumber, contactEmail, portId, portName } = job.data as {
          to: string;
          firstName: string;
          mooringNumber: string | null;
          contactEmail: string;
          portId?: string;
          portName?: string;
        };
        const { inquiryClientConfirmation } =
          await import('@/lib/email/templates/inquiry-client-confirmation');
        const { sendEmail } = await import('@/lib/email/index');
        const { resolveSubject } = await import('@/lib/email/resolve-subject');
        const { getBrandingShell } = await import('@/lib/email/branding-resolver');
        const branding = await getBrandingShell(portId);
        const email = await inquiryClientConfirmation(
          { firstName, mooringNumber, contactEmail, portName },
          { branding },
        );
        const subject = await resolveSubject({
          key: 'inquiry_client_confirmation',
          portId,
          fallback: email.subject,
          tokens: {
            portName: portName ?? 'the marina',
            recipientName: firstName,
            mooringNumber: mooringNumber ?? '',
          },
        });
        await sendEmail(to, subject, email.html, undefined, email.text, portId);
        break;
      }
      case 'send-inquiry-sales-notification': {
        const { to, fullName, email, phone, mooringNumber, crmUrl, portId, portName } =
          job.data as {
            to: string;
            fullName: string;
            email: string;
            phone: string;
            mooringNumber: string | null;
            crmUrl: string;
            portId?: string;
            portName?: string;
          };
        const { inquirySalesNotification } =
          await import('@/lib/email/templates/inquiry-sales-notification');
        const { sendEmail } = await import('@/lib/email/index');
        const { resolveSubject } = await import('@/lib/email/resolve-subject');
        const { getBrandingShell } = await import('@/lib/email/branding-resolver');
        const branding = await getBrandingShell(portId);
        const notification = await inquirySalesNotification(
          {
            fullName,
            email,
            phone,
            mooringNumber,
            crmUrl,
            portName,
          },
          { branding },
        );
        const subject = await resolveSubject({
          key: 'inquiry_sales_notification',
          portId,
          fallback: notification.subject,
          tokens: {
            portName: portName ?? 'the marina',
            clientName: fullName,
            mooringNumber: mooringNumber ?? '',
            email,
          },
        });
        await sendEmail(to, subject, notification.html, undefined, notification.text, portId);
        break;
      }
      case 'notification-digest': {
        // Recurring scheduler entry (hourly). The dispatcher gates on
        // each port's configured digest time + timezone so this is a
        // cheap no-op for hours that don't match.
        const { runNotificationDigest } =
          await import('@/lib/services/notification-digest.service');
        await runNotificationDigest();
        break;
      }
      default:
        logger.warn({ jobName: job.name }, 'Unknown email job');
    }
  },
  {
    connection: { url: env.REDIS_URL } as ConnectionOptions,
    concurrency: QUEUE_CONFIGS.email.concurrency,
  },
);

emailWorker.on('failed', (job, err) => {
  logger.error({ jobId: job?.id, jobName: job?.name, err }, 'Email job failed');
});

attachWorkerAudit(emailWorker, 'email');
