#!/usr/bin/env node

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

/**
 * ⚡ 任务生成器
 * 专门负责生成NestJS任务/队列文件
 */
class JobGenerator extends BaseGenerator {
  constructor() {
    super('JobGenerator');
    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.jobStats = {
      jobsCreated: 0,
      jobsSkipped: 0
    };
  }

  /**
   * 运行任务生成
   */
  async run() {
    try {
      console.log('⚡ 启动任务生成器...');
      console.log('目标：生成NestJS任务/队列文件\n');

      // 加载PHP文件发现结果
      await this.loadDiscoveryData();
      
      // 生成任务
      await this.generateJobs();
      
      // 输出统计报告
      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 generateJobs() {
    console.log('   🔨 生成任务...');
    
    // 检查是否有任务数据
    if (!this.discoveryData.jobs || Object.keys(this.discoveryData.jobs).length === 0) {
      console.log('   ⚠️  未发现PHP任务，跳过生成');
      return;
    }
    
    for (const [moduleName, jobs] of Object.entries(this.discoveryData.jobs)) {
      // 检查PHP项目是否有对应的任务目录
      if (!this.hasPHPJobs(moduleName)) {
        console.log(`   ⚠️  模块 ${moduleName} 在PHP项目中无任务，跳过`);
        continue;
      }
      
      for (const [jobName, jobInfo] of Object.entries(jobs)) {
        await this.createJob(moduleName, jobName, jobInfo);
        this.stats.jobsCreated++;
      }
    }
    
    console.log(`   ✅ 生成了 ${this.stats.jobsCreated} 个任务`);
  }

  /**
   * 创建任务
   */
  async createJob(moduleName, jobName, jobInfo) {
    const jobDir = path.join(this.config.nestjsBasePath, moduleName, 'jobs');
    this.ensureDir(jobDir);
    
    const normalizedBase = jobName.replace(/Job$/i, '');
    const jobPath = path.join(
      jobDir, 
      `${this.toPascalCase(normalizedBase)}Job.ts`
    );
    
    // 检查是否有对应的PHP任务文件
    const phpJobPath = path.join(this.config.phpBasePath, 'app/job', moduleName, `${jobName}.php`);
    if (!fs.existsSync(phpJobPath)) {
      console.log(`     ❌ 未找到PHP任务文件，跳过生成: ${phpJobPath}`);
      return;
    }
    
    const content = this.generateJobContent(moduleName, jobName);
    this.writeFile(jobPath, content, `Job for ${moduleName}/${jobName}`);
    this.jobStats.jobsCreated++;
  }

  /**
   * 生成任务内容
   */
  generateJobContent(moduleName, jobName) {
    const baseName = jobName.replace(/Job$/i, '');
    const className = `${this.toPascalCase(baseName)}Job`;
    
    return `import { Injectable, Logger } from '@nestjs/common';
import { InjectQueue } from '@nestjs/bullmq';
import { Queue } from 'bullmq';
import { BusinessException } from '@wwjCommon/exceptions/business.exception';

/**
 * ${className} - 基于NestJS BullMQ
 * 参考: https://docs.nestjs.com/techniques/queues
 * 对应 Java: @Async + RabbitMQ
 * 对应 PHP: think\queue
 */
@Injectable()
export class ${className} {
  private readonly logger = new Logger(${className}.name);

  constructor(
    @InjectQueue('${moduleName}') private readonly queue: Queue
  ) {}

  /**
   * 添加任务到队列 - 使用BullMQ标准API
   * 参考: https://docs.nestjs.com/techniques/queues#producers
   */
  async addJob(data: any, options?: any) {
    try {
      const job = await this.queue.add('${baseName}', data, options);
      this.logger.log(\`${baseName} job added to queue: \${job.id}\`, data);
      return job;
    } catch (error) {
      this.logger.error('Failed to add ${baseName} job to queue:', error);
      throw new BusinessException('${baseName}任务添加失败');
    }
  }

  /**
   * 处理队列任务
   * 使用Core层基础设施：统一队列服务、异常处理、日志服务
   */
  async processJob(data: any) {
    this.logger.log('${baseName} job processing:', data);
    
    try {
      // 任务逻辑
      await this.executeJob(data);
      this.logger.log('${baseName} job completed successfully');
    } catch (error) {
      this.logger.error('${baseName} job failed:', error);
      // 使用Core层异常处理
      throw new BusinessException('${baseName}任务处理失败', error);
    }
  }

  /**
   * 执行任务
   * 使用Core层基础设施：日志服务、异常处理
   */
  private async executeJob(data: any) {
    // 实现具体的任务逻辑
    // 例如：
    // - 数据清理
    // - 报表生成
    // - 邮件发送
    // - 数据同步
    // - 备份操作
    
    this.logger.log('Executing ${baseName} job logic with data:', data);
    
    // 模拟异步操作
    await new Promise(resolve => setTimeout(resolve, 1000));
    
    this.logger.log('${baseName} job logic completed');
  }

  /**
   * 手动触发任务
   * 使用Core层基础设施：日志服务、异常处理
   */
  async triggerJob(data?: any) {
    this.logger.log('Manually triggering ${baseName} job...');
    try {
      await this.executeJob(data || {});
    } catch (error) {
      this.logger.error('Failed to trigger ${baseName} job:', error);
      // 使用Core层异常处理
      throw new BusinessException('${baseName}任务触发失败', error);
    }
  }
}`;
  }

  /**
   * 转换为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任务
   */
  hasPHPJobs(moduleName) {
    const phpProjectPath = path.join(__dirname, '../../niucloud-php/niucloud');
    const jobPath = path.join(phpProjectPath, 'app/job', moduleName);
    return fs.existsSync(jobPath);
  }

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

  /**
   * 输出统计报告
   */
  printStats() {
    super.printStats({
      'Jobs Created': this.jobStats.jobsCreated,
      'Jobs Skipped': this.jobStats.jobsSkipped
    });
  }
}

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

module.exports = JobGenerator;
