const fs = require('fs');
const path = require('path');

/**
 * NestJS模块生成器
 * 为每个模块创建对应的.module.ts文件并正确引用所有组件
 */
class ModuleGenerator {
  constructor() {
    this.config = {
      nestjsBasePath: '/Users/wanwu/Documents/wwjcloud/wwjcloud-nsetjs/wwjcloud-nest/src/core',
      discoveryResultPath: './php-discovery-result.json',
      whitelistModules: [], // 空数组=全部业务模块，结合黑名单过滤
      blacklistModules: ['job','queue','workerman','lang','menu','system'],
      includeTypeOrmFeature: true
    };
    
    this.discoveryData = null;
    this.stats = {
      createdModules: 0,
      updatedModules: 0,
      errors: 0
    };
  }

  /**
   * 运行模块生成
   */
  async run() {
    try {
      console.log('🚀 启动NestJS模块生成器...');
      console.log('目标：为每个模块创建.module.ts文件并正确引用所有组件\n');

      // 第1阶段：加载PHP文件发现结果
      console.log('📊 第1阶段：加载PHP文件发现结果...');
      await this.loadDiscoveryData();
      console.log('   ✅ 成功加载PHP文件发现结果');

      // 第2阶段：扫描现有文件结构
      console.log('\n📊 第2阶段：扫描现有文件结构...');
      const moduleStructure = await this.scanModuleStructure();
      console.log(`   ✅ 扫描了 ${Object.keys(moduleStructure).length} 个模块`);

      // 第3阶段：生成模块文件
      console.log('\n📊 第3阶段：生成模块文件...');
      await this.generateModules(moduleStructure);
      console.log(`   ✅ 生成了 ${this.stats.createdModules} 个模块文件`);

      // 第4阶段：生成统计报告
      console.log('\n📊 第4阶段：生成统计报告...');
      this.generateStatsReport();

    } catch (error) {
      console.error('❌ 生成过程中发生错误:', error.message);
      this.stats.errors++;
      throw error;
    }
  }

  /**
   * 加载PHP文件发现结果
   */
  async loadDiscoveryData() {
    try {
      const data = fs.readFileSync(this.config.discoveryResultPath, 'utf8');
      this.discoveryData = JSON.parse(data);
    } catch (error) {
      console.log(`   ⚠️  未找到发现结果文件，跳过加载: ${error.message}`);
      this.discoveryData = {};
    }
  }

  /**
   * 扫描模块结构
   */
  async scanModuleStructure() {
    const moduleStructure = {};
    const commonPath = this.config.nestjsBasePath;

    if (!fs.existsSync(commonPath)) {
      console.log('   ⚠️  common目录不存在');
      return moduleStructure;
    }

    const modules = fs.readdirSync(commonPath, { withFileTypes: true })
      .filter(dirent => dirent.isDirectory())
      .map(dirent => dirent.name);

    for (const moduleName of modules) {
      if (this.shouldSkipModule(moduleName)) {
        console.log(`   ⏭️  跳过非业务模块: ${moduleName}`);
        continue;
      }
      const modulePath = path.join(commonPath, moduleName);
      moduleStructure[moduleName] = {
        controllers: this.scanControllers(modulePath),
        services: this.scanServices(modulePath),
        entities: this.scanEntities(modulePath),
        validators: this.scanValidators(modulePath),
        middlewares: this.scanMiddlewares(modulePath),
        jobs: this.scanJobs(modulePath),
        listeners: this.scanListeners(modulePath),
        commands: this.scanCommands(modulePath),
        dicts: this.scanDicts(modulePath)
      };
    }

    return moduleStructure;
  }

  /**
   * 读取实际文件中的类名
   */
  getActualClassName(filePath) {
    try {
      if (!fs.existsSync(filePath)) {
        return null;
      }
      
      const content = fs.readFileSync(filePath, 'utf8');
      const match = content.match(/export\s+(?:class|interface|enum)\s+(\w+)/);
      return match ? match[1] : null;
    } catch (error) {
      console.error(`读取文件 ${filePath} 时出错:`, error.message);
      return null;
    }
  }

  /**
   * 扫描控制器
   */
  scanControllers(modulePath) {
    const controllers = [];
    const controllersPath = path.join(modulePath, 'controllers');
    
    if (fs.existsSync(controllersPath)) {
      const layers = ['adminapi', 'api'];
      for (const layer of layers) {
        const layerPath = path.join(controllersPath, layer);
        if (fs.existsSync(layerPath)) {
          const allFiles = fs.readdirSync(layerPath);
          const controllerFiles = allFiles.filter(file => file.endsWith('.controller.ts'));
          
          if (controllerFiles.length > 0) {
            console.log(`    发现 ${layer} 层控制器: ${controllerFiles.join(', ')}`);
          }
          
          const files = controllerFiles.map(file => {
            const filePath = path.join(layerPath, file);
            const actualClassName = this.getActualClassName(filePath);
            return {
              name: actualClassName || this.guessControllerClassName(file),
              path: `./controllers/${layer}/${file}`,
              layer: layer
            };
          });
          controllers.push(...files);
        }
      }
    }
    
    return controllers;
  }

  /**
   * 扫描服务
   */
  scanServices(modulePath) {
    const services = [];
    const servicesPath = path.join(modulePath, 'services');
    
    if (fs.existsSync(servicesPath)) {
      const layers = ['admin', 'api', 'core'];
      for (const layer of layers) {
        const layerPath = path.join(servicesPath, layer);
        if (fs.existsSync(layerPath)) {
          const files = fs.readdirSync(layerPath)
            .filter(file => file.endsWith('.service.ts'))
            .map(file => {
              const filePath = path.join(layerPath, file);
              const actualClassName = this.getActualClassName(filePath);
              return {
                name: actualClassName || this.guessServiceClassName(file, layer),
                path: `./services/${layer}/${file}`,
                layer: layer
              };
            });
          services.push(...files);
        }
      }
    }
    
    return services;
  }

  /**
   * 扫描实体
   */
  scanEntities(modulePath) {
    const entities = [];
    const entitiesPath = path.join(modulePath, 'entity');
    
    if (fs.existsSync(entitiesPath)) {
      const files = fs.readdirSync(entitiesPath)
        .filter(file => file.endsWith('.entity.ts'))
        .map(file => ({
          name: this.getActualClassName(path.join(entitiesPath, file)) || this.guessEntityClassName(file),
          path: `./entity/${file}`
        }));
      entities.push(...files);
    }
    
    return entities;
  }

  /**
   * 扫描验证器
   */
  scanValidators(modulePath) {
    const validators = [];
    const validatorsPath = path.join(modulePath, 'dto');
    
    if (fs.existsSync(validatorsPath)) {
      const files = fs.readdirSync(validatorsPath, { recursive: true })
        .filter(file => file.endsWith('.ts') && !file.endsWith('.d.ts'))
        .map(file => ({
          name: file.replace('.ts', ''),
          path: `./dto/${file}`
        }));
      validators.push(...files);
    }
    
    return validators;
  }

  /**
   * 扫描中间件
   */
  scanMiddlewares(modulePath) {
    const middlewares = [];
    const middlewaresPath = path.join(modulePath, 'guards');
    
    if (fs.existsSync(middlewaresPath)) {
      const files = fs.readdirSync(middlewaresPath)
        .filter(file => file.endsWith('.ts') && !file.endsWith('.d.ts'))
        .map(file => ({
          name: file.replace('.ts', ''),
          path: `./guards/${file}`
        }));
      middlewares.push(...files);
    }
    
    return middlewares;
  }

  /**
   * 扫描任务
   */
  scanJobs(modulePath) {
    const jobs = [];
    const jobsPath = path.join(modulePath, 'jobs');
    
    if (fs.existsSync(jobsPath)) {
      const files = fs.readdirSync(jobsPath)
        .filter(file => file.endsWith('.ts') && !file.endsWith('.d.ts'))
        .map(file => ({
          name: file.replace('.ts', ''),
          path: `./jobs/${file}`
        }));
      jobs.push(...files);
    }
    
    return jobs;
  }

  /**
   * 扫描监听器
   */
  scanListeners(modulePath) {
    const listeners = [];
    const listenersPath = path.join(modulePath, 'listeners');
    
    if (fs.existsSync(listenersPath)) {
      const files = fs.readdirSync(listenersPath)
        .filter(file => file.endsWith('.ts') && !file.endsWith('.d.ts'))
        .map(file => ({
          name: file.replace('.ts', ''),
          path: `./listeners/${file}`
        }));
      listeners.push(...files);
    }
    
    return listeners;
  }

  /**
   * 扫描命令
   */
  scanCommands(modulePath) {
    const commands = [];
    const commandsPath = path.join(modulePath, 'commands');
    
    if (fs.existsSync(commandsPath)) {
      const files = fs.readdirSync(commandsPath)
        .filter(file => file.endsWith('.ts') && !file.endsWith('.d.ts'))
        .map(file => ({
          name: file.replace('.ts', ''),
          path: `./commands/${file}`
        }));
      commands.push(...files);
    }
    
    return commands;
  }

  /**
   * 扫描字典
   */
  scanDicts(modulePath) {
    const dicts = [];
    const dictsPath = path.join(modulePath, 'dicts');
    
    if (fs.existsSync(dictsPath)) {
      const files = fs.readdirSync(dictsPath)
        .filter(file => file.endsWith('.ts') && !file.endsWith('.d.ts'))
        .map(file => ({
          name: file.replace('.ts', ''),
          path: `./dicts/${file}`
        }));
      dicts.push(...files);
    }
    
    return dicts;
  }

  /**
   * 生成模块文件
   */
  async generateModules(moduleStructure) {
    console.log('   🔨 生成模块文件...');
    
    for (const [moduleName, components] of Object.entries(moduleStructure)) {
      try {
        await this.generateModuleFile(moduleName, components);
        this.stats.createdModules++;
      } catch (error) {
        console.error(`   ❌ 生成模块 ${moduleName} 失败:`, error.message);
        this.stats.errors++;
      }
    }
  }

  /**
   * 生成单个模块文件
   */
  async generateModuleFile(moduleName, components) {
    const modulePath = path.join(this.config.nestjsBasePath, moduleName, `${moduleName}.module.ts`);
    
    // 生成模块内容
    const moduleContent = this.generateModuleContent(moduleName, components);
    
    // 确保目录存在
    this.ensureDir(path.dirname(modulePath));
    
    // 写入文件
    fs.writeFileSync(modulePath, moduleContent);
    console.log(`     ✅ 创建模块: ${moduleName}/${moduleName}.module.ts`);
  }

  /**
   * 生成模块内容
   */
  generateModuleContent(moduleName, components) {
    const className = this.toPascalCase(moduleName) + 'Module';
    
    let imports = [];
    let controllers = [];
    let providers = [];
    let exports = [];
    let importSet = new Set(); // 用于去重

    // TypeORM feature (可选)
    const entityClassNames = components.entities.map(e => e.name).filter(Boolean);
    if (this.config.includeTypeOrmFeature && entityClassNames.length > 0) {
      importSet.add(`import { TypeOrmModule } from '@nestjs/typeorm';`);
      imports.push(`TypeOrmModule.forFeature([${entityClassNames.join(', ')}])`);
    }

    // 导入控制器并注册
    for (const controller of components.controllers) {
      importSet.add(`import { ${controller.name} } from '${controller.path}';`);
      controllers.push(controller.name);
    }

    // 导入服务并注册  
    for (const service of components.services) {
      if (!importSet.has(`import { ${service.name} } from '${service.path}';`)) {
        importSet.add(`import { ${service.name} } from '${service.path}';`);
        providers.push(`${service.name}`);
      }
    }

    // 导入实体（如果需要）
    for (const entity of components.entities) {
      if (!importSet.has(`import { ${entity.name} } from '${entity.path}';`)) {
        importSet.add(`import { ${entity.name} } from '${entity.path}';`);
      }
    }

    // 组合最终内容
    const moduleContent = `${Array.from(importSet).join('\n')}

import { Module } from '@nestjs/common';

@Module({
  imports: [${imports.join(', ')}],
  controllers: [${controllers.join(', ')}],
  providers: [${providers.join(', ')}],
  exports: [${exports.join(', ')}],
})
export class ${className} {}
`;

    return moduleContent;
  }

  /**
   * 从文件内容获取导出的类名
   */
  getActualClassName(filePath) {
    try {
      if (!fs.existsSync(filePath)) return null;
      const content = fs.readFileSync(filePath, 'utf8');
      const match = content.match(/export\s+class\s+(\w+)/);
      return match ? match[1] : null;
    } catch (error) {
      return null;
    }
  }

  /**
   * 由 kebab-case 实体文件名推测类名
   * 例如: member.entity.ts -> MemberEntity
   */
  guessEntityClassName(fileName) {
    const base = fileName.replace(/\.entity\.ts$/i, '');
    return this.kebabToPascal(base) + 'Entity';
  }

  /**
   * 由 kebab-case 控制器文件名推测类名
   * 例如: member-level.controller.ts -> MemberLevelController
   */
  guessControllerClassName(fileName) {
    const base = fileName.replace(/\.controller\.ts$/i, '');
    return this.kebabToPascal(base) + 'Controller';
  }

  /**
   * 由 kebab-case 服务文件名推测类名
   * 例如: member-level.service.ts -> MemberLevelService
   */
  guessServiceClassName(fileName, layer) {
    const base = fileName.replace(/\.service\.ts$/i, '');
    return this.kebabToPascal(base) + 'Service';
  }

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

  /**
   * 转换为PascalCase
   */
  toPascalCase(str) {
    return str.replace(/(^|_)([a-z])/g, (match, p1, p2) => p2.toUpperCase());
  }

  /**
   * kebab-case 转 PascalCase
   */
  kebabToPascal(str) {
    return str
      .split('-')
      .filter(Boolean)
      .map(s => s.charAt(0).toUpperCase() + s.slice(1))
      .join('');
  }

  shouldSkipModule(moduleName) {
    if (this.config.whitelistModules && this.config.whitelistModules.length > 0) {
      if (!this.config.whitelistModules.includes(moduleName)) return true;
    }
    if (this.config.blacklistModules && this.config.blacklistModules.includes(moduleName)) {
      return true;
    }
    return false;
  }

  /**
   * 获取层前缀
   */
  getLayerPrefix(layer, serviceName) {
    // 如果服务名已经包含Core前缀，则不需要再添加
    if (layer === 'core' && serviceName.toLowerCase().startsWith('core')) {
      return '';
    }
    
    const layerMap = {
      'admin': 'Admin',
      'api': 'Api',
      'core': 'Core'
    };
    return layerMap[layer] || '';
  }

  /**
   * 检查是否需要别名
   */
  needsAlias(layer, serviceName) {
    // 如果服务名已经包含层前缀，则不需要别名
    if (layer === 'core' && serviceName.toLowerCase().startsWith('core')) {
      return false;
    }
    return true;
  }

  /**
   * 生成统计报告
   */
  generateStatsReport() {
    console.log('\n📊 NestJS模块生成统计报告:');
    console.log('============================================================');
    console.log(`   📁 创建模块: ${this.stats.createdModules} 个`);
    console.log(`   🔄 更新模块: ${this.stats.updatedModules} 个`);
    console.log(`   ❌ 错误数量: ${this.stats.errors} 个`);
    console.log('============================================================');
    console.log('\n✅ 🎉 NestJS模块生成完成！');
  }
}

// 运行模块生成器
if (require.main === module) {
  const generator = new ModuleGenerator();
  generator.run().catch(console.error);
}

module.exports = ModuleGenerator;
