/**
 * 邮件服务
 * 
 * 功能描述：
 * - 提供邮件发送的核心功能
 * - 支持多种邮件模板和场景
 * - 集成主流邮件服务提供商
 * 
 * 支持的邮件类型：
 * - 邮箱验证码
 * - 密码重置验证码
 * - 欢迎邮件
 * - 系统通知
 * 
 * 职责分离：
 * - 邮件发送：核心邮件发送功能实现
 * - 模板管理：各种邮件模板的生成和管理
 * - 配置管理：邮件服务配置和连接管理
 * 
 * 最近修改：
 * - 2026-01-07: 代码规范优化 - 清理未使用的导入(BadRequestException)，移除多余注释
 * - 2026-01-07: 代码规范优化 - 完善方法注释和修改记录
 * 
 * @author moyin
 * @version 1.0.1
 * @since 2025-12-17
 * @lastModified 2026-01-07
 */

import { Injectable, Logger } from '@nestjs/common';
import { ConfigService } from '@nestjs/config';
import * as nodemailer from 'nodemailer';
import { Transporter } from 'nodemailer';

/**
 * 邮件发送选项接口
 */
export interface EmailOptions {
  /** 收件人邮箱 */
  to: string;
  /** 邮件主题 */
  subject: string;
  /** 邮件内容（HTML格式） */
  html: string;
  /** 邮件内容（纯文本格式） */
  text?: string;
}

/**
 * 验证码邮件选项接口
 */
export interface VerificationEmailOptions {
  /** 收件人邮箱 */
  email: string;
  /** 验证码 */
  code: string;
  /** 用户昵称 */
  nickname?: string;
  /** 验证码用途 */
  purpose: 'email_verification' | 'password_reset' | 'login_verification';
}

/**
 * 邮件发送结果接口
 */
export interface EmailSendResult {
  /** 是否成功 */
  success: boolean;
  /** 是否为测试模式 */
  isTestMode: boolean;
  /** 错误信息（如果失败） */
  error?: string;
}

/**
 * 邮件服务类
 * 
 * 职责：
 * - 邮件发送功能：提供统一的邮件发送接口
 * - 模板管理：管理各种邮件模板（验证码、欢迎邮件等）
 * - 配置管理：处理邮件服务配置和连接
 * - 测试模式：支持开发环境的邮件测试模式
 * 
 * 主要方法：
 * - sendEmail() - 通用邮件发送方法
 * - sendVerificationCode() - 发送验证码邮件
 * - sendWelcomeEmail() - 发送欢迎邮件
 * - verifyConnection() - 验证邮件服务连接
 * 
 * 使用场景：
 * - 用户注册时发送邮箱验证码
 * - 密码重置时发送重置验证码
 * - 用户注册成功后发送欢迎邮件
 * - 登录验证时发送登录验证码
 */
@Injectable()
export class EmailService {
  private readonly logger = new Logger(EmailService.name);
  private transporter: Transporter;

  constructor(private readonly configService: ConfigService) {
    this.initializeTransporter();
  }

  /**
   * 初始化邮件传输器
   * 
   * 业务逻辑：
   * 1. 从配置服务获取邮件服务配置（主机、端口、安全设置、认证信息）
   * 2. 检查是否配置了用户名和密码
   * 3. 未配置：创建测试模式传输器（streamTransport）
   * 4. 已配置：创建真实SMTP传输器
   * 5. 记录初始化结果到日志
   * 6. 设置transporter实例
   */
  private initializeTransporter(): void {
    const emailConfig = {
      host: this.configService.get<string>('EMAIL_HOST', 'smtp.gmail.com'),
      port: this.configService.get<number>('EMAIL_PORT', 587),
      secure: this.configService.get<boolean>('EMAIL_SECURE', false), // true for 465, false for other ports
      auth: {
        user: this.configService.get<string>('EMAIL_USER'),
        pass: this.configService.get<string>('EMAIL_PASS'),
      },
    };

    // 如果没有配置邮件服务，使用测试模式
    if (!emailConfig.auth.user || !emailConfig.auth.pass) {
      this.logger.warn('邮件服务未配置，将使用测试模式（邮件不会真实发送）');
      this.transporter = nodemailer.createTransport({
        streamTransport: true,
        newline: 'unix',
        buffer: true
      });
    } else {
      this.transporter = nodemailer.createTransport(emailConfig);
      this.logger.log('邮件服务初始化成功');
    }
  }

  /**
   * 检查是否为测试模式
   * 
   * 业务逻辑：
   * 1. 检查transporter的options配置
   * 2. 判断是否设置了streamTransport选项
   * 3. streamTransport为true表示测试模式
   * 4. 返回测试模式状态
   * 
   * @returns 是否为测试模式，true表示测试模式，false表示生产模式
   * 
   * @example
   * ```typescript
   * if (emailService.isTestMode()) {
   *   console.log('当前为测试模式，邮件不会真实发送');
   * }
   * ```
   */
  isTestMode(): boolean {
    return !!(this.transporter.options as any).streamTransport;
  }

  /**
   * 发送邮件
   * 
   * 业务逻辑：
   * 1. 构建邮件选项（发件人、收件人、主题、内容）
   * 2. 检查是否为测试模式
   * 3. 测试模式：输出邮件内容到控制台，不真实发送
   * 4. 生产模式：通过SMTP服务器发送邮件
   * 5. 记录发送结果和错误信息
   * 6. 返回发送结果状态
   * 
   * @param options 邮件选项
   * @returns 发送结果，包含成功状态、测试模式标识和错误信息
   * @throws Error 当邮件发送失败时抛出错误（已捕获并返回在结果中）
   * 
   * @example
   * ```typescript
   * const result = await emailService.sendEmail({
   *   to: 'user@example.com',
   *   subject: '测试邮件',
   *   html: '<p>邮件内容</p>',
   *   text: '邮件内容'
   * });
   * if (result.success) {
   *   console.log('邮件发送成功');
   * }
   * ```
   */
  async sendEmail(options: EmailOptions): Promise<EmailSendResult> {
    try {
      const mailOptions = {
        from: this.configService.get<string>('EMAIL_FROM', '"Whale Town Game" <noreply@whaletown.com>'),
        to: options.to,
        subject: options.subject,
        html: options.html,
        text: options.text,
      };

      const isTestMode = this.isTestMode();

      // 如果是测试模式，输出邮件内容到控制台
      if (isTestMode) {
        this.logger.warn('=== 邮件发送（测试模式 - 邮件未真实发送） ===');
        this.logger.warn(`收件人: ${options.to}`);
        this.logger.warn(`主题: ${options.subject}`);
        this.logger.warn(`内容: ${options.text || '请查看HTML内容'}`);
        this.logger.warn('⚠️  注意: 这是测试模式，邮件不会真实发送到用户邮箱');
        this.logger.warn('💡 提示: 请在 .env 文件中配置邮件服务以启用真实发送');
        this.logger.warn('================================================');
        return { success: true, isTestMode: true };
      }

      // 真实发送邮件
      const result = await this.transporter.sendMail(mailOptions);
      this.logger.log(`✅ 邮件发送成功: ${options.to}`);
      return { success: true, isTestMode: false };
    } catch (error) {
      this.logger.error(`❌ 邮件发送失败: ${options.to}`, error instanceof Error ? error.stack : String(error));
      return { 
        success: false, 
        isTestMode: this.isTestMode(),
        error: error instanceof Error ? error.message : String(error)
      };
    }
  }

  /**
   * 发送邮箱验证码
   * 
   * 业务逻辑：
   * 1. 根据验证码用途选择对应的邮件主题和模板
   * 2. 邮箱验证：使用邮箱验证模板
   * 3. 密码重置：使用密码重置模板
   * 4. 登录验证：使用登录验证模板
   * 5. 生成HTML邮件内容和纯文本内容
   * 6. 调用sendEmail方法发送邮件
   * 7. 返回发送结果
   * 
   * @param options 验证码邮件选项
   * @returns 发送结果，包含成功状态和错误信息
   * @throws Error 当邮件发送失败时（已捕获并返回在结果中）
   * 
   * @example
   * ```typescript
   * const result = await emailService.sendVerificationCode({
   *   email: 'user@example.com',
   *   code: '123456',
   *   nickname: '张三',
   *   purpose: 'email_verification'
   * });
   * ```
   */
  async sendVerificationCode(options: VerificationEmailOptions): Promise<EmailSendResult> {
    const { email, code, nickname, purpose } = options;

    let subject: string;
    let template: string;

    if (purpose === 'email_verification') {
      subject = '【Whale Town】邮箱验证码';
      template = this.getEmailVerificationTemplate(code, nickname);
    } else if (purpose === 'password_reset') {
      subject = '【Whale Town】密码重置验证码';
      template = this.getPasswordResetTemplate(code, nickname);
    } else if (purpose === 'login_verification') {
      subject = '【Whale Town】登录验证码';
      template = this.getLoginVerificationTemplate(code, nickname);
    } else {
      subject = '【Whale Town】验证码';
      template = this.getEmailVerificationTemplate(code, nickname);
    }

    return await this.sendEmail({
      to: email,
      subject,
      html: template,
      text: `您的验证码是：${code}，5分钟内有效，请勿泄露给他人。`
    });
  }

  /**
   * 发送欢迎邮件
   * 
   * 业务逻辑：
   * 1. 设置欢迎邮件主题
   * 2. 生成包含用户昵称的欢迎邮件模板
   * 3. 模板包含游戏特色介绍（建造创造、社交互动、任务挑战）
   * 4. 调用sendEmail方法发送邮件
   * 5. 返回发送结果
   * 
   * @param email 邮箱地址
   * @param nickname 用户昵称
   * @returns 发送结果，包含成功状态和错误信息
   * @throws Error 当邮件发送失败时（已捕获并返回在结果中）
   * 
   * @example
   * ```typescript
   * const result = await emailService.sendWelcomeEmail(
   *   'newuser@example.com',
   *   '新用户'
   * );
   * ```
   */
  async sendWelcomeEmail(email: string, nickname: string): Promise<EmailSendResult> {
    const subject = '🎮 欢迎加入 Whale Town！';
    const template = this.getWelcomeTemplate(nickname);

    return await this.sendEmail({
      to: email,
      subject,
      html: template,
      text: `欢迎 ${nickname} 加入 Whale Town 像素游戏世界！`
    });
  }

  /**
   * 获取邮箱验证模板
   * 
   * @param code 验证码
   * @param nickname 用户昵称
   * @returns HTML模板
   */
  private getEmailVerificationTemplate(code: string, nickname?: string): string {
    return `
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>邮箱验证</title>
    <style>
        body { font-family: Arial, sans-serif; line-height: 1.6; color: #333; }
        .container { max-width: 600px; margin: 0 auto; padding: 20px; }
        .header { background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 30px; text-align: center; border-radius: 10px 10px 0 0; }
        .content { background: #f9f9f9; padding: 30px; border-radius: 0 0 10px 10px; }
        .code-box { background: #fff; border: 2px dashed #667eea; padding: 20px; text-align: center; margin: 20px 0; border-radius: 8px; }
        .code { font-size: 32px; font-weight: bold; color: #667eea; letter-spacing: 5px; }
        .footer { text-align: center; margin-top: 20px; color: #666; font-size: 12px; }
        .warning { background: #fff3cd; border: 1px solid #ffeaa7; padding: 15px; border-radius: 5px; margin: 20px 0; }
    </style>
</head>
<body>
    <div class="container">
        <div class="header">
            <h1>🐋 Whale Town</h1>
            <p>邮箱验证</p>
        </div>
        <div class="content">
            <h2>你好${nickname ? ` ${nickname}` : ''}！</h2>
            <p>感谢您注册 Whale Town 像素游戏！为了确保您的账户安全，请使用以下验证码完成邮箱验证：</p>
            
            <div class="code-box">
                <div class="code">${code}</div>
                <p style="margin: 10px 0 0 0; color: #666;">验证码</p>
            </div>
            
            <div class="warning">
                <strong>⚠️ 安全提醒：</strong>
                <ul style="margin: 10px 0 0 20px;">
                    <li>验证码 5 分钟内有效</li>
                    <li>请勿将验证码泄露给他人</li>
                    <li>如非本人操作，请忽略此邮件</li>
                </ul>
            </div>
            
            <p>完成验证后，您就可以开始您的像素世界冒险之旅了！</p>
        </div>
        <div class="footer">
            <p>此邮件由系统自动发送，请勿回复</p>
            <p>© 2025 Whale Town Game. All rights reserved.</p>
        </div>
    </div>
</body>
</html>`;
  }

  /**
   * 获取密码重置模板
   * 
   * @param code 验证码
   * @param nickname 用户昵称
   * @returns HTML模板
   */
  private getPasswordResetTemplate(code: string, nickname?: string): string {
    return `
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>密码重置</title>
    <style>
        body { font-family: Arial, sans-serif; line-height: 1.6; color: #333; }
        .container { max-width: 600px; margin: 0 auto; padding: 20px; }
        .header { background: linear-gradient(135deg, #ff6b6b 0%, #ee5a24 100%); color: white; padding: 30px; text-align: center; border-radius: 10px 10px 0 0; }
        .content { background: #f9f9f9; padding: 30px; border-radius: 0 0 10px 10px; }
        .code-box { background: #fff; border: 2px dashed #ff6b6b; padding: 20px; text-align: center; margin: 20px 0; border-radius: 8px; }
        .code { font-size: 32px; font-weight: bold; color: #ff6b6b; letter-spacing: 5px; }
        .footer { text-align: center; margin-top: 20px; color: #666; font-size: 12px; }
        .warning { background: #fff3cd; border: 1px solid #ffeaa7; padding: 15px; border-radius: 5px; margin: 20px 0; }
    </style>
</head>
<body>
    <div class="container">
        <div class="header">
            <h1>🔐 密码重置</h1>
            <p>Whale Town 账户安全</p>
        </div>
        <div class="content">
            <h2>你好${nickname ? ` ${nickname}` : ''}！</h2>
            <p>我们收到了您的密码重置请求。请使用以下验证码来重置您的密码：</p>
            
            <div class="code-box">
                <div class="code">${code}</div>
                <p style="margin: 10px 0 0 0; color: #666;">密码重置验证码</p>
            </div>
            
            <div class="warning">
                <strong>🛡️ 安全提醒：</strong>
                <ul style="margin: 10px 0 0 20px;">
                    <li>验证码 5 分钟内有效</li>
                    <li>请勿将验证码泄露给他人</li>
                    <li>如非本人操作，请立即联系客服</li>
                    <li>重置密码后请妥善保管新密码</li>
                </ul>
            </div>
            
            <p>如果您没有请求重置密码，请忽略此邮件，您的账户仍然安全。</p>
        </div>
        <div class="footer">
            <p>此邮件由系统自动发送，请勿回复</p>
            <p>© 2025 Whale Town Game. All rights reserved.</p>
        </div>
    </div>
</body>
</html>`;
  }

  /**
   * 获取登录验证码模板
   * 
   * @param code 验证码
   * @param nickname 用户昵称
   * @returns HTML模板
   */
  private getLoginVerificationTemplate(code: string, nickname?: string): string {
    return `
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>登录验证码</title>
    <style>
        body { font-family: Arial, sans-serif; line-height: 1.6; color: #333; }
        .container { max-width: 600px; margin: 0 auto; padding: 20px; }
        .header { background: linear-gradient(135deg, #667eea 0%, #764ba2 100%); color: white; padding: 30px; text-align: center; border-radius: 10px 10px 0 0; }
        .content { background: #f9f9f9; padding: 30px; border-radius: 0 0 10px 10px; }
        .code-box { background: #fff; border: 2px dashed #667eea; padding: 20px; text-align: center; margin: 20px 0; border-radius: 8px; }
        .code { font-size: 32px; font-weight: bold; color: #667eea; letter-spacing: 5px; }
        .footer { text-align: center; margin-top: 20px; color: #666; font-size: 12px; }
        .info { background: #e3f2fd; border: 1px solid #bbdefb; padding: 15px; border-radius: 5px; margin: 20px 0; }
    </style>
</head>
<body>
    <div class="container">
        <div class="header">
            <h1>🔐 登录验证码</h1>
            <p>Whale Town 安全登录</p>
        </div>
        <div class="content">
            <h2>你好${nickname ? ` ${nickname}` : ''}！</h2>
            <p>您正在使用验证码登录 Whale Town。请使用以下验证码完成登录：</p>
            
            <div class="code-box">
                <div class="code">${code}</div>
                <p style="margin: 10px 0 0 0; color: #666;">登录验证码</p>
            </div>
            
            <div class="info">
                <strong>📱 使用说明：</strong>
                <ul style="margin: 10px 0 0 20px;">
                    <li>验证码 5 分钟内有效</li>
                    <li>请在登录页面输入此验证码</li>
                    <li>验证码仅限本次登录使用</li>
                    <li>请勿将验证码泄露给他人</li>
                </ul>
            </div>
            
            <p>如果您没有尝试登录，请忽略此邮件，或联系客服确认账户安全。</p>
        </div>
        <div class="footer">
            <p>此邮件由系统自动发送，请勿回复</p>
            <p>© 2025 Whale Town Game. All rights reserved.</p>
        </div>
    </div>
</body>
</html>`;
  }

  /**
   * 获取欢迎邮件模板
   * 
   * @param nickname 用户昵称
   * @returns HTML模板
   */
  private getWelcomeTemplate(nickname: string): string {
    return `
<!DOCTYPE html>
<html>
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>欢迎加入 Whale Town</title>
    <style>
        body { font-family: Arial, sans-serif; line-height: 1.6; color: #333; }
        .container { max-width: 600px; margin: 0 auto; padding: 20px; }
        .header { background: linear-gradient(135deg, #4ecdc4 0%, #44a08d 100%); color: white; padding: 30px; text-align: center; border-radius: 10px 10px 0 0; }
        .content { background: #f9f9f9; padding: 30px; border-radius: 0 0 10px 10px; }
        .feature-box { background: #fff; padding: 20px; margin: 15px 0; border-radius: 8px; border-left: 4px solid #4ecdc4; }
        .footer { text-align: center; margin-top: 20px; color: #666; font-size: 12px; }
    </style>
</head>
<body>
    <div class="container">
        <div class="header">
            <h1>🎮 欢迎加入 Whale Town！</h1>
            <p>像素世界的冒险即将开始</p>
        </div>
        <div class="content">
            <h2>欢迎你，${nickname}！</h2>
            <p>恭喜您成功注册 Whale Town 像素游戏！您现在已经成为我们像素世界大家庭的一员了。</p>
            
            <div class="feature-box">
                <h3>🏗️ 建造与创造</h3>
                <p>在像素世界中建造您的梦想家园，发挥无限创意！</p>
            </div>
            
            <div class="feature-box">
                <h3>🤝 社交互动</h3>
                <p>与其他玩家交流互动，结交志同道合的朋友！</p>
            </div>
            
            <div class="feature-box">
                <h3>🎯 任务挑战</h3>
                <p>完成各种有趣的任务，获得丰厚的奖励！</p>
            </div>
            
            <p><strong>现在就开始您的像素冒险之旅吧！</strong></p>
            <p>如果您在游戏过程中遇到任何问题，随时可以联系我们的客服团队。</p>
        </div>
        <div class="footer">
            <p>祝您游戏愉快！</p>
            <p>© 2025 Whale Town Game. All rights reserved.</p>
        </div>
    </div>
</body>
</html>`;
  }

  /**
   * 验证邮件服务配置
   * 
   * 业务逻辑：
   * 1. 调用transporter的verify方法测试连接
   * 2. 验证SMTP服务器连接是否正常
   * 3. 验证认证信息是否有效
   * 4. 记录验证结果到日志
   * 5. 返回验证结果状态
   * 
   * @returns 验证结果，true表示连接成功，false表示连接失败
   * @throws Error 当连接验证失败时（已捕获并返回false）
   * 
   * @example
   * ```typescript
   * const isConnected = await emailService.verifyConnection();
   * if (isConnected) {
   *   console.log('邮件服务连接正常');
   * } else {
   *   console.log('邮件服务连接失败');
   * }
   * ```
   */
  async verifyConnection(): Promise<boolean> {
    try {
      await this.transporter.verify();
      this.logger.log('邮件服务连接验证成功');
      return true;
    } catch (error) {
      this.logger.error('邮件服务连接验证失败', error instanceof Error ? error.stack : String(error));
      return false;
    }
  }
}