import { Processor, WorkerHost } from '@nestjs/bullmq';
import { Logger } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import { Job } from 'bullmq';
import { PrismaService } from '../../prisma/prisma.service';
import { EmailJobData } from './email.service';
import * as nodemailer from 'nodemailer';

@Processor('email-send')
export class EmailSendProcessor extends WorkerHost {
  private readonly logger = new Logger(EmailSendProcessor.name);
  private transporter: nodemailer.Transporter | null = null;

  constructor(
    private readonly prisma: PrismaService,
    private readonly config: ConfigService,
  ) {
    super();
  }

  private getTransporter(): nodemailer.Transporter {
    if (this.transporter) return this.transporter;

    const host = this.config.get<string>('SMTP_HOST', 'localhost');
    const port = this.config.get<number>('SMTP_PORT', 587);
    const user = this.config.get<string>('SMTP_USER', '');
    const pass = this.config.get<string>('SMTP_PASS', '');
    const secure = this.config.get<boolean>('SMTP_SECURE', false);

    this.transporter = nodemailer.createTransport({
      host,
      port,
      secure,
      ...(user && pass
        ? { auth: { user, pass } }
        : {}),
    });

    return this.transporter;
  }

  async process(job: Job<EmailJobData>): Promise<void> {
    const { emailLogId, clubId, to, subject, html, text } = job.data;

    this.logger.log(`Sending email ${emailLogId} to ${to}`);

    try {
      const fromName = this.config.get<string>('SMTP_FROM_NAME', 'MyFitCRM');
      const fromEmail = this.config.get<string>('SMTP_FROM_EMAIL', 'noreply@myfitcrm.ru');

      const info = await this.getTransporter().sendMail({
        from: `"${fromName}" <${fromEmail}>`,
        to,
        subject,
        html,
        ...(text ? { text } : {}),
      });

      const providerMessageId = info.messageId ?? null;

      await this.prisma.emailLog.update({
        where: { id: emailLogId },
        data: {
          status: 'SENT',
          sentAt: new Date(),
          providerMessageId,
        },
      });

      this.logger.log(`Email sent: ${emailLogId} (messageId: ${providerMessageId})`);
    } catch (error: any) {
      this.logger.error(`Email send failed: ${emailLogId} — ${error.message}`);

      await this.prisma.emailLog.update({
        where: { id: emailLogId },
        data: {
          status: 'FAILED',
          errorMessage: error.message?.slice(0, 500),
        },
      });

      throw error; // BullMQ will retry
    }
  }
}
