import { Injectable, Logger, ServiceUnavailableException } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import * as nodemailer from 'nodemailer';
import SMTPTransport from 'nodemailer/lib/smtp-transport';

@Injectable()
export class EmailService {
  private readonly logger = new Logger(EmailService.name);
  private transporter: nodemailer.Transporter<SMTPTransport.SentMessageInfo> | null = null;

  constructor(private readonly configService: ConfigService) {}

  async sendVerificationCode(email: string, code: string, expiresMinutes: number): Promise<void> {
    const subject = 'تأكيد البريد الإلكتروني - Oudelaa';
    const text = [
      'مرحباً،',
      `رمز تأكيد الحساب الخاص بك هو: ${code}`,
      `صلاحية الرمز: ${expiresMinutes} دقيقة.`,
      'إذا لم تطلب هذا الرمز، تجاهل هذه الرسالة.',
    ].join('\n');
    const html = this.buildCodeEmailHtml({
      title: 'تأكيد البريد الإلكتروني',
      intro: 'استخدم الرمز التالي لإكمال تفعيل حسابك في Oudelaa:',
      code,
      expiresMinutes,
      footerNote: 'إذا لم تطلب هذا الرمز، يمكنك تجاهل الرسالة بأمان.',
    });
    await this.send(email, subject, text, html);
  }

  async sendPasswordResetCode(email: string, code: string, expiresMinutes: number): Promise<void> {
    const subject = 'إعادة تعيين كلمة المرور - Oudelaa';
    const text = [
      'مرحباً،',
      `رمز إعادة تعيين كلمة المرور هو: ${code}`,
      `صلاحية الرمز: ${expiresMinutes} دقيقة.`,
      'إذا لم تطلب إعادة تعيين كلمة المرور، ننصحك بتغيير كلمة المرور مباشرة.',
    ].join('\n');
    const html = this.buildCodeEmailHtml({
      title: 'إعادة تعيين كلمة المرور',
      intro: 'استخدم الرمز التالي لإعادة تعيين كلمة المرور:',
      code,
      expiresMinutes,
      footerNote: 'إذا لم تطلب إعادة التعيين، تجاهل هذه الرسالة وقم بمراجعة أمان حسابك.',
    });
    await this.send(email, subject, text, html);
  }

  private buildCodeEmailHtml(params: {
    title: string;
    intro: string;
    code: string;
    expiresMinutes: number;
    footerNote: string;
  }): string {
    return `
      <div style="font-family: Arial, sans-serif; background:#f6f8fb; padding:24px; direction:rtl; text-align:right;">
        <div style="max-width:520px; margin:0 auto; background:#ffffff; border-radius:12px; padding:24px; border:1px solid #e8edf3;">
          <h2 style="margin:0 0 12px; color:#111827;">${params.title}</h2>
          <p style="margin:0 0 16px; color:#374151; line-height:1.7;">${params.intro}</p>
          <div style="font-size:32px; letter-spacing:6px; font-weight:700; color:#0f172a; background:#f1f5f9; border-radius:10px; text-align:center; padding:14px 8px; margin:0 0 14px;">
            ${params.code}
          </div>
          <p style="margin:0 0 10px; color:#475569;">صلاحية الرمز: <strong>${params.expiresMinutes} دقيقة</strong></p>
          <p style="margin:0; color:#64748b; font-size:13px;">${params.footerNote}</p>
          <hr style="border:none; border-top:1px solid #e5e7eb; margin:18px 0;" />
          <p style="margin:0; color:#94a3b8; font-size:12px;">Oudelaa Team</p>
        </div>
      </div>
    `;
  }

  private async send(to: string, subject: string, text: string, html: string): Promise<void> {
    const enabled = this.configService.get<boolean>('email.enabled', { infer: true });
    if (!enabled) {
      const nodeEnv = this.configService.get<string>('nodeEnv', { infer: true });
      if (nodeEnv !== 'production') {
        this.logger.warn(`Email delivery is disabled. Skipping email to ${to}`);
        return;
      }

      throw new ServiceUnavailableException('Email delivery is disabled');
    }

    const fromName = this.configService.get<string>('email.fromName', { infer: true }) ?? 'Oudelaa';
    const fromEmail = this.configService.get<string>('email.fromEmail', { infer: true }) ?? '';
    if (!fromEmail) {
      throw new ServiceUnavailableException('Email sender is not configured');
    }

    const transporter = this.getTransporter();
    try {
      await transporter.sendMail({
        from: `${fromName} <${fromEmail}>`,
        to,
        subject,
        text,
        html,
      });
    } catch (error) {
      this.logger.error(`Failed to send email to ${to}`, error as Error);
      const nodeEnv = this.configService.get<string>('nodeEnv', { infer: true });
      if (nodeEnv === 'development') {
        const err = error as Error & { code?: string; message?: string };
        throw new ServiceUnavailableException(
          `Failed to send verification email (${err.code ?? 'SMTP_ERROR'}: ${err.message ?? 'unknown'})`,
        );
      }
      throw new ServiceUnavailableException('Failed to send verification email');
    }
  }

  private getTransporter(): nodemailer.Transporter<SMTPTransport.SentMessageInfo> {
    if (this.transporter) {
      return this.transporter;
    }

    const host = this.configService.get<string>('email.smtpHost', { infer: true }) ?? '';
    const port = this.configService.get<number>('email.smtpPort', { infer: true }) ?? 587;
    const secure = this.configService.get<boolean>('email.smtpSecure', { infer: true }) ?? false;
    const user = this.configService.get<string>('email.smtpUser', { infer: true }) ?? '';
    const pass = this.configService.get<string>('email.smtpPass', { infer: true }) ?? '';

    if (!host || !user || !pass) {
      throw new ServiceUnavailableException('SMTP settings are not configured');
    }

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

    return this.transporter;
  }
}
