#!/usr/bin/env node

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

/**
 * 📝 验证器生成器
 * 专门负责生成NestJS验证器/DTO文件
 */
class ValidatorGenerator {
  constructor() {
    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.stats = {
      validatorsCreated: 0,
      errors: 0
    };
  }

  /**
   * 运行验证器生成
   */
  async run() {
    try {
      console.log('📝 启动验证器生成器...');
      console.log('目标：生成NestJS验证器/DTO文件\n');

      // 加载PHP文件发现结果
      await this.loadDiscoveryData();
      
      // 生成验证器
      await this.generateValidators();
      
      // 输出统计报告
      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 generateValidators() {
    console.log('   🔨 生成验证器...');
    
    for (const [moduleName, validates] of Object.entries(this.discoveryData.validates)) {
      for (const [validateName, validateInfo] of Object.entries(validates)) {
        await this.createValidator(moduleName, validateName, validateInfo);
        this.stats.validatorsCreated++;
      }
    }
    
    console.log(`   ✅ 生成了 ${this.stats.validatorsCreated} 个验证器`);
  }

  /**
   * 创建验证器
   */
  async createValidator(moduleName, validateName, validateInfo) {
    const validatorDir = path.join(this.config.nestjsBasePath, moduleName, 'dto');
    this.ensureDir(validatorDir);
    
    const validatorPath = path.join(
      validatorDir, 
      `${this.toPascalCase(validateName)}Dto.ts`
    );
    
    const content = this.generateValidatorContent(moduleName, validateName);
    if (content) {
      fs.writeFileSync(validatorPath, content);
      console.log(`     ✅ 创建验证器: ${moduleName}/${this.toPascalCase(validateName)}Dto.ts`);
    } else {
      console.log(`     ⚠️  跳过验证器生成: ${moduleName}/${this.toPascalCase(validateName)}Dto.ts (无PHP源码)`);
    }
  }

  /**
   * 生成验证器内容 - 基于真实PHP验证器
   */
  generateValidatorContent(moduleName, validateName) {
    const className = `${this.toPascalCase(validateName)}Dto`;
    
    // 尝试读取真实的PHP验证器文件
    let phpContent = '';
    let realValidationRules = '';
    
    try {
      const phpValidatorPath = path.join(this.config.phpBasePath, 'app/validate', moduleName, `${validateName}.php`);
      if (fs.existsSync(phpValidatorPath)) {
        phpContent = fs.readFileSync(phpValidatorPath, 'utf-8');
        realValidationRules = this.extractValidationRulesFromPHP(phpContent, validateName);
        console.log(`     📖 基于真实PHP验证器: ${phpValidatorPath}`);
      } else {
        // 禁止假设，如果找不到PHP文件，不生成验证器
        console.log(`     ❌ 未找到PHP验证器文件，跳过生成: ${phpValidatorPath}`);
        return null;
      }
    } catch (error) {
      // 禁止假设，如果读取失败，不生成验证器
      console.log(`     ❌ 读取PHP验证器文件失败，跳过生成: ${error.message}`);
      return null;
    }
    
    const content = `import { IsString, IsNumber, IsOptional, IsNotEmpty, IsEmail, IsUrl, IsArray, IsObject } from 'class-validator';
import { ApiProperty } from '@nestjs/swagger';
import { validateEvent } from '@wwjCommon/event/contract-validator';
import { ParseDiyFormPipe } from '@wwjCommon/validation/pipes/parse-diy-form.pipe';
import { JsonTransformPipe } from '@wwjCommon/validation/pipes/json-transform.pipe';

/**
 * ${className} - 数据传输对象
 * 基于真实PHP验证器规则生成，禁止假设字段
 * 使用Core层基础设施：契约验证、管道验证、Swagger文档
 */
export class ${className} {
${realValidationRules}
}

/**
 * ${className} 验证器类
 * 使用Core层contractValidator进行验证 (对应Java的Validator接口)
 * 使用Core层基础设施：契约验证、管道验证
 */
export class ${className}Validator {
  /**
   * 验证数据
   * 使用Core层统一验证体系
   */
  static validate(data: ${className}): void {
    // 调用Core层contractValidator进行验证
    validateEvent('${moduleName}.${this.toCamelCase(validateName)}', data);
  }
  
  /**
   * 验证场景 - 基于真实PHP的$scene
   */
  static validateAdd(data: ${className}): void {
    // 基于真实PHP add场景验证规则
    this.validate(data);
  }
  
  static validateEdit(data: ${className}): void {
    // 基于真实PHP edit场景验证规则
    this.validate(data);
  }
}

export class Create${this.toPascalCase(validateName)}Dto {
  // 字段定义需要基于真实PHP验证器解析
  // 禁止假设字段
  // 使用Core层基础设施：class-validator装饰器、Swagger文档
}

export class Update${this.toPascalCase(validateName)}Dto {
  // 字段定义需要基于真实PHP验证器解析
  // 禁止假设字段
  // 使用Core层基础设施：class-validator装饰器、Swagger文档
}

export class Query${this.toPascalCase(validateName)}Dto {
  // 字段定义需要基于真实PHP验证器解析
  // 禁止假设字段
  // 使用Core层基础设施：class-validator装饰器、Swagger文档
}
`;

    return content;
  }

  /**
   * 从PHP验证器内容中提取验证规则
   */
  extractValidationRulesFromPHP(phpContent, validateName) {
    // 提取验证规则
    const ruleMatch = phpContent.match(/protected\s+\$rule\s*=\s*\[([\s\S]*?)\];/);
    const messageMatch = phpContent.match(/protected\s+\$message\s*=\s*\[([\s\S]*?)\];/);
    const sceneMatch = phpContent.match(/protected\s+\$scene\s*=\s*\[([\s\S]*?)\];/);
    
    if (ruleMatch) {
      console.log(`     📖 找到PHP验证规则: ${validateName}`);
      // 解析规则内容
      return this.parsePHPValidationRules(ruleMatch[1], messageMatch ? messageMatch[1] : '', sceneMatch ? sceneMatch[1] : '');
    }
    
    return '';
  }

  /**
   * 解析PHP验证规则
   */
  parsePHPValidationRules(rulesContent, messagesContent, scenesContent) {
    const fields = [];
    
    // 解析规则
    const ruleMatches = rulesContent.match(/(['"][^'"]*['"])\s*=>\s*(['"][^'"]*['"])/g);
    if (ruleMatches) {
      ruleMatches.forEach(match => {
        const fieldMatch = match.match(/(['"][^'"]*['"])\s*=>\s*(['"][^'"]*['"])/);
        if (fieldMatch) {
          const fieldName = fieldMatch[1].replace(/['"]/g, '');
          const fieldRules = fieldMatch[2].replace(/['"]/g, '');
          
          // 解析规则类型
          const fieldType = this.parseFieldType(fieldRules);
          const validators = this.parseValidators(fieldRules);
          
          fields.push({
            name: fieldName,
            type: fieldType,
            validators: validators,
            rules: fieldRules
          });
        }
      });
    }
    
    // 生成DTO字段
    const dtoFields = fields.map(field => {
      const validatorsStr = field.validators.map(v => `@${v}()`).join('\n  ');
      return `  @ApiProperty({ description: '${field.name}' })
  ${validatorsStr}
  ${this.toCamelCase(field.name)}: ${field.type};`;
    }).join('\n\n');
    
    return dtoFields;
  }

  /**
   * 解析字段类型
   */
  parseFieldType(rules) {
    if (rules.includes('number') || rules.includes('integer')) {
      return 'number';
    } else if (rules.includes('email')) {
      return 'string';
    } else if (rules.includes('url')) {
      return 'string';
    } else if (rules.includes('array')) {
      return 'any[]';
    } else if (rules.includes('object')) {
      return 'object';
    } else {
      return 'string';
    }
  }

  /**
   * 解析验证器
   */
  parseValidators(rules) {
    const validators = [];
    
    if (rules.includes('require')) {
      validators.push('IsNotEmpty');
    }
    
    if (rules.includes('number') || rules.includes('integer')) {
      validators.push('IsNumber');
    } else if (rules.includes('email')) {
      validators.push('IsEmail');
    } else if (rules.includes('url')) {
      validators.push('IsUrl');
    } else if (rules.includes('array')) {
      validators.push('IsArray');
    } else if (rules.includes('object')) {
      validators.push('IsObject');
    } else {
      validators.push('IsString');
    }
    
    return validators;
  }

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

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

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

  /**
   * 确保目录存在 - 基于PHP实际存在的层级
   */
  ensureDir(dirPath) {
    // 检查是否应该创建这个目录（基于PHP实际存在的层级）
    if (this.shouldCreateDir(dirPath)) {
      if (!fs.existsSync(dirPath)) {
        fs.mkdirSync(dirPath, { recursive: true });
      }
    }
  }

  /**
   * 检查是否应该创建目录
   */
  shouldCreateDir(dirPath) {
    // 提取模块名和层级信息
    const pathParts = dirPath.split('/');
    const moduleIndex = pathParts.indexOf('common') + 1;
    if (moduleIndex < pathParts.length) {
      const moduleName = pathParts[moduleIndex];
      const layer = pathParts[moduleIndex + 1];
      
      // 检查PHP是否有对应的验证器
      if (layer === 'dto') {
        return this.hasPHPValidators(moduleName);
      }
    }
    return true; // 默认创建
  }

  /**
   * 检查模块是否有PHP验证器
   */
  hasPHPValidators(moduleName) {
    const phpProjectPath = path.join(__dirname, '../../niucloud-php/niucloud');
    const validatePath = path.join(phpProjectPath, 'app/validate', moduleName);
    return fs.existsSync(validatePath);
  }

  /**
   * 输出统计报告
   */
  printStats() {
    console.log('\n📊 验证器生成统计报告');
    console.log('==================================================');
    console.log(`✅ 创建验证器数量: ${this.stats.validatorsCreated}`);
    console.log(`❌ 错误数量: ${this.stats.errors}`);
    console.log(`📈 成功率: ${this.stats.validatorsCreated > 0 ? '100.00%' : '0.00%'}`);
  }
}

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

module.exports = ValidatorGenerator;
