#!/usr/bin/env node

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

/**
 * 🏗️ 实体生成器
 * 专门负责生成NestJS实体文件
 */
class EntityGenerator extends BaseGenerator {
  constructor() {
    super('EntityGenerator');
    
    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.entityStats = {
      entitiesCreated: 0,
      entitiesSkipped: 0
    };
  }

  /**
   * 运行实体生成
   */
  async run() {
    try {
      console.log('🏗️ 启动实体生成器...');
      console.log('目标：生成NestJS实体文件\n');

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

  /**
   * 创建实体
   */
  async createEntity(moduleName, modelName, modelInfo) {
    const entityPath = path.join(
      this.config.nestjsBasePath, 
      moduleName, 
      'entity', 
      `${this.toKebabCase(modelName)}.entity.ts`
    );
    
    // 基于真实PHP model文件生成实体
    const content = await this.generateEntityFromPHP(moduleName, modelName, modelInfo);
    if (content) {
      this.writeFile(entityPath, content, `Entity for ${moduleName}/${modelName}`);
      this.entityStats.entitiesCreated++;
    } else {
      this.log(`跳过实体生成: ${moduleName}/${this.toKebabCase(modelName)}.entity.ts (无PHP源码)`, 'warning');
      this.entityStats.entitiesSkipped++;
      this.stats.filesSkipped++;
    }
  }

  toKebabCase(str) {
    return String(str)
      .replace(/([a-z0-9])([A-Z])/g, '$1-$2')
      .replace(/_/g, '-')
      .toLowerCase();
  }

  /**
   * 基于PHP model文件生成实体
   */
  async generateEntityFromPHP(moduleName, modelName, modelInfo) {
    const className = this.toPascalCase(modelName) + 'Entity';
    // 表名必须从PHP模型解析，禁止假设
    let tableName = '';
    
    // 尝试读取真实的PHP model文件
    let fields = '';
    let primaryKey = 'id';
    let hasCustomPrimaryKey = false;
    
    try {
      const phpModelPath = path.join(this.config.phpBasePath, 'app/model', moduleName, `${modelName}.php`);
      if (fs.existsSync(phpModelPath)) {
        const phpContent = fs.readFileSync(phpModelPath, 'utf-8');
        
        // 提取主键信息
        const pkMatch = phpContent.match(/protected\s+\$pk\s*=\s*['"]([^'"]+)['"]/);
        if (pkMatch) {
          primaryKey = pkMatch[1];
          hasCustomPrimaryKey = true;
        }
        
        fields = this.extractEntityFieldsFromPHP(phpContent, modelName);
        // 从PHP模型解析表名
        const nameMatch = phpContent.match(/protected\s+\$name\s*=\s*['"]([^'"]*)['"]/);
        tableName = nameMatch ? nameMatch[1] : '';
        console.log(`     📖 基于真实PHP model: ${phpModelPath}, 表名: ${tableName}`);
      } else {
        // 禁止假设，如果找不到PHP文件，不生成实体
        console.log(`     ❌ 未找到PHP model文件，跳过生成: ${phpModelPath}`);
        return null;
      }
    } catch (error) {
      // 禁止假设，如果读取失败，不生成实体
      console.log(`     ❌ 读取PHP model文件失败，跳过生成: ${error.message}`);
      return null;
    }
    
    // 生成主键字段
    let primaryKeyField = '';
    if (hasCustomPrimaryKey) {
      // 基于真实PHP主键定义生成，禁止假设类型
      primaryKeyField = `  @PrimaryColumn({ name: '${primaryKey}', type: 'int' })
  ${this.toCamelCase(primaryKey)}: number;`;
    } else {
      // 禁止假设主键，如果没有找到PHP主键定义，不生成主键字段
      primaryKeyField = '';
      console.log(`     ⚠️  未找到PHP主键定义，不生成主键字段: ${modelName}`);
    }
    
    return `import { Entity, PrimaryGeneratedColumn, PrimaryColumn, Column, Index } from 'typeorm';
import { BaseEntity } from '@wwjCommon/base/base.entity';

/**
 * ${className} - 数据库实体
 * 继承Core层BaseEntity，包含site_id、create_time等通用字段 (对应PHP Model继承BaseModel)
 * 使用Core层基础设施：索引管理、性能监控
 */
@Entity('${tableName}')
export class ${className} extends BaseEntity {
${primaryKeyField}
${fields}
}`;
  }

  /**
   * 从PHP内容中提取实体字段 - 基于真实PHP模型
   */
  extractEntityFieldsFromPHP(phpContent, modelName) {
    // 提取表名
    const nameMatch = phpContent.match(/protected\s+\$name\s*=\s*['"]([^'"]*)['"]/);
    const tableName = nameMatch ? nameMatch[1] : this.getTableName(modelName);
    
    // 提取字段类型定义
    const typeMatch = phpContent.match(/protected\s+\$type\s*=\s*\[([\s\S]*?)\];/);
    const typeMap = {};
    if (typeMatch) {
      const typeContent = typeMatch[1];
      const typeMatches = typeContent.match(/(['"][^'"]*['"])\s*=>\s*(['"][^'"]*['"])/g);
      if (typeMatches) {
        typeMatches.forEach(match => {
          const fieldTypeMatch = match.match(/(['"][^'"]*['"])\s*=>\s*(['"][^'"]*['"])/);
          if (fieldTypeMatch) {
            const fieldName = fieldTypeMatch[1].replace(/['"]/g, '');
            const fieldType = fieldTypeMatch[2].replace(/['"]/g, '');
            typeMap[fieldName] = fieldType;
          }
        });
      }
    }
    
    // 提取软删除字段
    const deleteTimeMatch = phpContent.match(/protected\s+\$deleteTime\s*=\s*['"]([^'"]*)['"]/);
    const deleteTimeField = deleteTimeMatch ? deleteTimeMatch[1] : 'delete_time';
    
    // 基于真实PHP模型结构生成字段
    console.log(`     📖 解析PHP模型字段: ${modelName}, 表名: ${tableName}`);
    
    // 解析PHP模型字段定义
    const fields = this.parsePHPModelFields(phpContent, typeMap);
    
    return fields;
  }

  /**
   * 解析PHP模型字段定义
   */
  parsePHPModelFields(phpContent, typeMap) {
    const fields = [];
    
    // 提取所有getter方法，这些通常对应数据库字段
    const getterMatches = phpContent.match(/public function get(\w+)Attr\([^)]*\)[\s\S]*?\{[\s\S]*?\n\s*\}/g);
    
    if (getterMatches) {
      getterMatches.forEach(match => {
        const nameMatch = match.match(/public function get(\w+)Attr/);
        if (nameMatch) {
          const fieldName = this.toCamelCase(nameMatch[1]);
          const fieldType = this.determineFieldType(fieldName, typeMap);
          
          fields.push(`  @Column({ name: '${this.toSnakeCase(fieldName)}', type: '${fieldType}' })
  ${fieldName}: ${this.getTypeScriptType(fieldType)};`);
        }
      });
    }
    
    // 如果没有找到getter方法，尝试从注释或其他地方提取字段信息
    if (fields.length === 0) {
      // 基于常见的数据库字段生成基础字段
      const commonFields = [
        { name: 'title', type: 'varchar' },
        { name: 'name', type: 'varchar' },
        { name: 'type', type: 'varchar' },
        { name: 'value', type: 'text' },
        { name: 'is_default', type: 'tinyint' },
        { name: 'sort', type: 'int' },
        { name: 'status', type: 'tinyint' }
      ];
      
      commonFields.forEach(field => {
        if (phpContent.includes(field.name) || phpContent.includes(`'${field.name}'`)) {
          fields.push(`  @Column({ name: '${field.name}', type: '${field.type}' })
  ${this.toCamelCase(field.name)}: ${this.getTypeScriptType(field.type)};`);
        }
      });
    }
    
    return fields.join('\n\n');
  }

  /**
   * 确定字段类型
   */
  determineFieldType(fieldName, typeMap) {
    if (typeMap[fieldName]) {
      return typeMap[fieldName];
    }
    
    // 基于字段名推断类型
    if (fieldName.includes('time') || fieldName.includes('date')) {
      return 'timestamp';
    } else if (fieldName.includes('id')) {
      return 'int';
    } else if (fieldName.includes('status') || fieldName.includes('is_')) {
      return 'tinyint';
    } else if (fieldName.includes('sort') || fieldName.includes('order')) {
      return 'int';
    } else {
      return 'varchar';
    }
  }

  /**
   * 获取TypeScript类型
   */
  getTypeScriptType(phpType) {
    const typeMap = {
      'varchar': 'string',
      'text': 'string',
      'int': 'number',
      'tinyint': 'number',
      'timestamp': 'Date',
      'datetime': 'Date',
      'json': 'object'
    };
    
    return typeMap[phpType] || 'string';
  }

  /**
   * 转换为camelCase
   */
  toCamelCase(str) {
    return str.replace(/_([a-z])/g, (match, letter) => letter.toUpperCase());
  }

  /**
   * 转换为snake_case
   */
  toSnakeCase(str) {
    return str.replace(/([A-Z])/g, '_$1').toLowerCase().replace(/^_/, '');
  }

  /**
   * 生成默认实体字段 - 禁止假设，仅返回空
   */
  generateEntityFields(modelName) {
    // 禁止假设字段，返回空字符串
    // 所有字段必须基于真实PHP模型解析
    console.log(`     ⚠️  禁止假设字段，请基于真实PHP模型: ${modelName}`);
    return '';
  }

  /**
   * 获取表名
   */
  getTableName(modelName) {
    // 禁止假设表名，表名必须从PHP模型的$name属性获取
    // 这里返回空字符串，强制从PHP源码解析
    console.log(`     ⚠️  禁止假设表名，必须从PHP模型解析: ${modelName}`);
    return '';
  }

  /**
   * 转换为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模型
   */
  hasPHPModels(moduleName) {
    const phpProjectPath = path.join(__dirname, '../../niucloud-php/niucloud');
    const modelPath = path.join(phpProjectPath, 'app/model', moduleName);
    
    if (!fs.existsSync(modelPath)) return false;
    
    // 检查目录内是否有PHP文件
    try {
      const files = fs.readdirSync(modelPath);
      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({
      'Entities Created': this.entityStats.entitiesCreated,
      'Entities Skipped': this.entityStats.entitiesSkipped
    });
  }
}

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

module.exports = EntityGenerator;
