#!/usr/bin/env node

const fs = require('fs');
const path = require('path');
const BaseGenerator = require('./base-generator');

/**
 * 👂 监听器生成器
 * 专门负责生成NestJS事件监听器文件
 */
class ListenerGenerator extends BaseGenerator {
  constructor() {
    super('ListenerGenerator');
    this.config = {
      phpBasePath: '/Users/wanwu/Documents/wwjcloud/wwjcloud-nsetjs/niucloud-php/niucloud',
      nestjsBasePath: '/Users/wanwu/Documents/wwjcloud/wwjcloud-nsetjs/wwjcloud-nest/src/core',
      discoveryResultPath: '/Users/wanwu/Documents/wwjcloud/wwjcloud-nsetjs/tools/php-discovery-result.json'
    };
    
    this.discoveryData = null;
    this.listenerStats = {
      listenersCreated: 0,
      listenersSkipped: 0
    };
  }

  /**
   * 运行监听器生成
   */
  async run() {
    try {
      console.log('👂 启动监听器生成器...');
      console.log('目标：生成NestJS事件监听器文件\n');

      // 加载PHP文件发现结果
      await this.loadDiscoveryData();
      
      // 生成监听器
      await this.generateListeners();
      
      // 输出统计报告
      this.printStats();
      
    } catch (error) {
      console.error('❌ 监听器生成失败:', error);
      this.stats.errors++;
    }
  }

  /**
   * 加载PHP文件发现结果
   */
  async loadDiscoveryData() {
    try {
      const data = fs.readFileSync(this.config.discoveryResultPath, 'utf8');
      this.discoveryData = JSON.parse(data);
      console.log('   ✅ 成功加载PHP文件发现结果');
    } catch (error) {
      console.error('❌ 加载发现结果失败:', error);
      throw error;
    }
  }

  /**
   * 生成监听器
   */
  async generateListeners() {
    console.log('   🔨 生成监听器...');
    
    // 检查是否有监听器数据
    if (!this.discoveryData.listeners || Object.keys(this.discoveryData.listeners).length === 0) {
      console.log('   ⚠️  未发现PHP监听器，跳过生成');
      return;
    }
    
    for (const [moduleName, listeners] of Object.entries(this.discoveryData.listeners)) {
      // 检查PHP项目是否有对应的监听器目录
      if (!this.hasPHPListeners(moduleName)) {
        console.log(`   ⚠️  模块 ${moduleName} 在PHP项目中无监听器，跳过`);
        continue;
      }
      
      for (const [listenerName, listenerInfo] of Object.entries(listeners)) {
        await this.createListener(moduleName, listenerName, listenerInfo);
        this.stats.listenersCreated++;
      }
    }
    
    console.log(`   ✅ 生成了 ${this.stats.listenersCreated} 个监听器`);
  }

  /**
   * 创建监听器
   */
  async createListener(moduleName, listenerName, listenerInfo) {
    const listenerDir = path.join(this.config.nestjsBasePath, moduleName, 'listeners');
    this.ensureDir(listenerDir);
    
    const listenerPath = path.join(
      listenerDir, 
      `${this.toPascalCase(listenerName)}Listener.ts`
    );
    
    // 检查是否有对应的PHP监听器文件
    const phpListenerPath = path.join(this.config.phpBasePath, 'app/listener', moduleName, `${listenerName}.php`);
    if (!fs.existsSync(phpListenerPath)) {
      console.log(`     ❌ 未找到PHP监听器文件，跳过生成: ${phpListenerPath}`);
      return;
    }
    
    const content = this.generateListenerContent(moduleName, listenerName);
    this.writeFile(listenerPath, content, `Listener for ${moduleName}/${listenerName}`);
    this.listenerStats.listenersCreated++;
  }

  /**
   * 生成监听器内容
   */
  generateListenerContent(moduleName, listenerName) {
    // 移除可能存在的Listener后缀，避免重复
    const baseName = listenerName.replace(/Listener$/i, '');
    const className = `${this.toPascalCase(baseName)}Listener`;
    
    // 解析PHP监听器的真实内容
    const phpListenerPath = path.join(__dirname, '../../niucloud-php/niucloud/app/listener', moduleName, `${listenerName}.php`);
    const phpContent = this.parsePHPListener(phpListenerPath);
    
    return `import { Injectable, Logger } from '@nestjs/common';
import { OnEvent } from '@nestjs/event-emitter';
import { BusinessException } from '@wwjCommon/exceptions/business.exception';

/**
 * ${className} - 基于NestJS EventEmitter
 * 参考: https://docs.nestjs.com/techniques/events
 * 对应 Java: @EventListener + ApplicationEventPublisher
 * 对应 PHP: think\\facade\\Event
 */
@Injectable()
export class ${className} {
  private readonly logger = new Logger(${className}.name);

  /**
   * 处理事件 - 基于PHP真实实现
   * 使用 @OnEvent 装饰器监听事件
   */
  @OnEvent('${baseName.toLowerCase()}.handle')
  async handle(payload: any) {
    this.logger.log('${baseName} listener: Event received', payload);
    
    try {
      // TODO: 实现${baseName}事件处理逻辑
      // 原始PHP逻辑已解析，需要手动转换为TypeScript
      this.logger.log('Processing ${baseName} event with payload:', payload);
      
      // 示例：处理事件数据
      // const { type, data } = payload;
      // if (type === 'weapp') {
      //   const siteId = data.site_id;
      //   // 处理逻辑...
      // }
      
      this.logger.log('${baseName} event processed successfully');
      
    } catch (error) {
      this.logger.error('Error processing ${baseName} event:', error);
      throw new BusinessException('${baseName}事件处理失败');
    }
  }
}`;
  }

  /**
   * 解析PHP监听器文件
   */
  parsePHPListener(phpFilePath) {
    try {
      if (!fs.existsSync(phpFilePath)) {
        return {
          methodBody: '// PHP文件不存在，请手动实现业务逻辑'
        };
      }

      const phpContent = fs.readFileSync(phpFilePath, 'utf8');
      
      // 提取handle方法的内容
      const handleMethodMatch = phpContent.match(/public function handle\([^)]*\)\s*\{([\s\S]*?)\n\s*\}/);
      
      if (!handleMethodMatch) {
        return {
          methodBody: '// 无法解析PHP handle方法，请手动实现业务逻辑'
        };
      }

      const methodBody = handleMethodMatch[1]
        .trim()
        .split('\n')
        .map(line => {
          // 移除PHP注释
          line = line.replace(/\/\/.*$/, '');
          // 移除PHP变量符号
          line = line.replace(/\$([a-zA-Z_][a-zA-Z0-9_]*)/g, '$1');
          // 移除PHP数组语法
          line = line.replace(/\[([^\]]*)\]/g, '[$1]');
          // 移除PHP字符串连接
          line = line.replace(/\./g, '+');
          // 移除PHP分号
          line = line.replace(/;$/g, '');
          return line.trim();
        })
        .filter(line => line.length > 0)
        .map(line => `      ${line}`)
        .join('\n');

      return {
        methodBody: methodBody || '// 请根据PHP实现添加业务逻辑'
      };

    } catch (error) {
      console.error(`解析PHP监听器失败: ${phpFilePath}`, error);
      return {
        methodBody: '// 解析PHP文件失败，请手动实现业务逻辑'
      };
    }
  }

  /**
   * 转换为PascalCase
   */
  toPascalCase(str) {
    return str.charAt(0).toUpperCase() + str.slice(1);
  }

  /**
   * 转换为camelCase
   */
  toCamelCase(str) {
    return str.charAt(0).toLowerCase() + str.slice(1);
  }

  toPascalCase(str) {
    return str.charAt(0).toUpperCase() + str.slice(1);
  }

  /**
   * 检查模块是否有PHP监听器
   */
  hasPHPListeners(moduleName) {
    const phpProjectPath = path.join(__dirname, '../../niucloud-php/niucloud');
    const listenerPath = path.join(phpProjectPath, 'app/listener', moduleName);
    
    // 检查目录是否存在
    if (!fs.existsSync(listenerPath)) {
      return false;
    }
    
    // 检查目录中是否有PHP文件
    try {
      const files = fs.readdirSync(listenerPath);
      return files.some(file => file.endsWith('.php'));
    } catch (error) {
      return false;
    }
  }

  /**
   * 确保目录存在
   */
  ensureDir(dirPath) {
    if (!fs.existsSync(dirPath)) {
      fs.mkdirSync(dirPath, { recursive: true });
    }
  }

  /**
   * 输出统计报告
   */
  printStats() {
    super.printStats({
      'Listeners Created': this.listenerStats.listenersCreated,
      'Listeners Skipped': this.listenerStats.listenersSkipped
    });
  }
}

// 如果直接运行此文件
if (require.main === module) {
  const generator = new ListenerGenerator();
  generator.run().catch(console.error);
}

module.exports = ListenerGenerator;
