import { Injectable, Logger } from '@nestjs/common';
import { DbService, Tx } from '@/common/db/db.service';
import { emailOutbox } from '@/db/schema';
import { loadEnv } from '@/config/env';
import { requireRequestContext } from '@/common/context/request-context';

export interface QueuedEmail {
  to: string[];
  cc?: string[];
  subject: string;
  bodyHtml: string;
  attachments?: { documentId?: string; storageKey?: string; fileName?: string }[];
  refType?: string;
  refId?: string;
}

/**
 * Emails are queued in email_outbox inside the business transaction and sent by
 * the EmailSender job. MAIL_DRIVER=log writes them to the log (dev/test);
 * MAIL_DRIVER=smtp uses nodemailer (installed in production image).
 */
@Injectable()
export class MailService {
  private readonly logger = new Logger(MailService.name);
  private readonly env = loadEnv();

  constructor(private readonly db: DbService) {}

  async queue(mail: QueuedEmail, tx: Tx, tenantId?: string): Promise<string> {
    const tid = tenantId ?? requireRequestContext().tenantId;
    if (!tid) throw new Error('MailService.queue requires a tenant');
    const [row] = await tx
      .insert(emailOutbox)
      .values({ tenantId: tid, to: mail.to, cc: mail.cc ?? [], subject: mail.subject, bodyHtml: mail.bodyHtml, attachments: mail.attachments ?? [], refType: mail.refType, refId: mail.refId })
      .returning({ id: emailOutbox.id });
    return row.id;
  }

  /** Transport used by the sender job. */
  async deliver(mail: { to: string[]; cc: string[]; subject: string; html: string; attachments: { filename: string; content: Buffer }[] }): Promise<void> {
    if (this.env.MAIL_DRIVER === 'log') {
      this.logger.log(`[mail:log] to=${mail.to.join(',')} subject="${mail.subject}" attachments=${mail.attachments.length}`);
      return;
    }
    // eslint-disable-next-line @typescript-eslint/no-var-requires
    const nodemailer = require('nodemailer');
    const transport = nodemailer.createTransport({
      host: this.env.SMTP_HOST,
      port: this.env.SMTP_PORT ?? 587,
      secure: (this.env.SMTP_PORT ?? 587) === 465,
      auth: this.env.SMTP_USER ? { user: this.env.SMTP_USER, pass: this.env.SMTP_PASS } : undefined,
    });
    await transport.sendMail({ from: this.env.MAIL_FROM, to: mail.to.join(','), cc: mail.cc.join(','), subject: mail.subject, html: mail.html, attachments: mail.attachments });
  }
}
