const fs = require('fs');
const path = require('path');
const ConfigReader = require('../config/config-reader');
const FileUtils = require('../utils/file-utils');

/**
 * Generator untuk main module files
 */
class MainModuleGenerator {

  /**
   * Generate main module file
   * @param {string} moduleName - Nama module
   * @param {string} databaseType - Tipe database (postgres/oracle)
   * @param {Object} options - Generation options
   * @returns {boolean} True jika berhasil
   */
  static createMainModule(moduleName, databaseType = 'postgres', options = {}) {
    try {
      console.log(``);
      console.log(`Generating main module: ${moduleName} (${databaseType})`);

      // Setup directories
      const paths = FileUtils.setupModuleDirectories(moduleName);

      // Generate main module file
      const moduleFilePath = path.join(paths.modules, `${moduleName}.js`);

      // Check if file already exists
      if (fs.existsSync(moduleFilePath) && !options.force) {
        console.log(`Main module ${moduleName}.js already exists, skipping generation`);
        return true;
      }

      // Generate module content
      const moduleContent = this.generateModuleContent(moduleName, databaseType, options);

      // Write module file tanpa backup (archive system digunakan sebagai gantinya)
      FileUtils.writeFileWithBackup(moduleFilePath, moduleContent, false);

      console.log(`Main module ${moduleName}.js generated successfully`);
      return true;

    } catch (error) {
      console.error(`Error generating main module ${moduleName}:`, error.message);
      throw error;
    }
  }

  /**
   * Generate module content based on database type
   * @param {string} moduleName - Nama module
   * @param {string} databaseType - Tipe database
   * @param {Object} options - Generation options
   * @returns {string} Generated module content
   */
  static generateModuleContent(moduleName, databaseType, options = {}) {
    try {
      // Try to load database-specific template
      if (databaseType === 'sqlite') {
        const sqliteContent = this.generateSqliteModuleContent(moduleName, options);
        if (sqliteContent) {
          console.log(`Using SQLite-specific template for ${moduleName}`);
          return sqliteContent;
        } else {
          console.log(`SQLite template not available, falling back to PostgreSQL template`);
          databaseType = 'postgres';
        }
      }

      if (databaseType === 'mysql') {
        const mysqlContent = this.generateMysqlModuleContent(moduleName, options);
        if (mysqlContent) {
          console.log(`Using MySQL-specific template for ${moduleName}`);
          return mysqlContent;
        } else {
          console.log(`MySQL template not available, falling back to PostgreSQL template`);
          databaseType = 'postgres';
        }
      }

      if (databaseType === 'oracle') {
        const oracleContent = this.generateOracleModuleContent(moduleName, options);
        if (oracleContent) {
          console.log(`Using Oracle-specific template for ${moduleName}`);
          return oracleContent;
        } else {
          console.log(`Oracle template not available, falling back to PostgreSQL template`);
          databaseType = 'postgres';
        }
      }

      // Default PostgreSQL template
      return this.generatePostgresModuleContent(moduleName, options);

    } catch (error) {
      console.error(`Error generating module content: ${error.message}`);
      throw error;
    }
  }

  /**
   * Generate Oracle-specific module content
   * @param {string} moduleName - Nama module
   * @param {Object} options - Generation options
   * @returns {string|null} Oracle module content atau null jika tidak tersedia
   */
  static generateOracleModuleContent(moduleName, options = {}) {
    try {
      // Try to load Oracle utilities
      const oracleUtils = this.loadOracleUtils();
      if (oracleUtils && oracleUtils.createOracleMainModuleTemplate) {
        const content = oracleUtils.createOracleMainModuleTemplate(moduleName);
        if (content && content.trim().length > 0) {
          return content;
        }
      }
      return null;
    } catch (error) {
      console.warn(`Oracle utils not available: ${error.message}`);
      return null;
    }
  }

  /**
   * Load Oracle utilities dengan error handling
   * @returns {Object|null} Oracle utils object atau null
   */
  static loadOracleUtils() {
    try {
      return require('../templates/oracle-template');
    } catch (error) {
      return null;
    }
  }

  /**
   * Generate SQLite-specific module content
   * @param {string} moduleName - Nama module
   * @param {Object} options - Generation options
   * @returns {string|null} SQLite module content atau null jika tidak tersedia
   */
  static generateSqliteModuleContent(moduleName, options = {}) {
    try {
      const sqliteUtils = this.loadSqliteUtils();
      if (sqliteUtils && sqliteUtils.createSqliteMainModuleTemplate) {
        const content = sqliteUtils.createSqliteMainModuleTemplate(moduleName);
        if (content && content.trim().length > 0) {
          return content;
        }
      }
      return null;
    } catch (error) {
      console.warn(`SQLite utils not available: ${error.message}`);
      return null;
    }
  }

  /**
   * Load SQLite utilities dengan error handling
   * @returns {Object|null} SQLite utils object atau null
   */
  static loadSqliteUtils() {
    try {
      return require('../templates/sqlite-template');
    } catch (error) {
      return null;
    }
  }

  /**
   * Generate MySQL-specific module content
   * @param {string} moduleName - Nama module
   * @param {Object} options - Generation options
   * @returns {string|null} MySQL module content atau null jika tidak tersedia
   */
  static generateMysqlModuleContent(moduleName, options = {}) {
    try {
      const mysqlUtils = this.loadMysqlUtils();
      if (mysqlUtils && mysqlUtils.createMysqlMainModuleTemplate) {
        const content = mysqlUtils.createMysqlMainModuleTemplate(moduleName);
        if (content && content.trim().length > 0) {
          return content;
        }
      }
      return null;
    } catch (error) {
      console.warn(`MySQL utils not available: ${error.message}`);
      return null;
    }
  }

  /**
   * Load MySQL utilities dengan error handling
   * @returns {Object|null} MySQL utils object atau null
   */
  static loadMysqlUtils() {
    try {
      return require('../templates/mysql-template');
    } catch (error) {
      return null;
    }
  }

  /**
   * Load PostgreSQL utilities dengan error handling
   * @returns {Object|null} PostgreSQL utils object atau null
   */
  static loadPostgresUtils() {
    try {
      return require('../templates/postgres-template');
    } catch (error) {
      return null;
    }
  }

  /**
   * Generate PostgreSQL module content
   * @param {string} moduleName - Nama module
   * @param {Object} options - Generation options
   * @returns {string|null} PostgreSQL module content atau null
   */
  static generatePostgresModuleContent(moduleName, options = {}) {
    try {
      const postgresUtils = this.loadPostgresUtils();
      if (postgresUtils && postgresUtils.createPostgresMainModuleTemplate) {
        const content = postgresUtils.createPostgresMainModuleTemplate(moduleName);
        if (content && content.trim().length > 0) {
          return content;
        }
      }
      return null;
    } catch (error) {
      console.warn(`PostgreSQL main module template not available: ${error.message}`);
      return null;
    }
  }

  /**
   * Validate module generation options
   * @param {Object} options - Generation options
   * @returns {Object} Validated options
   */
  static validateGenerationOptions(options = {}) {
    const validated = {
      force: Boolean(options.force),
      createBackup: options.createBackup !== false,
      addHealthEndpoints: options.addHealthEndpoints !== false,
      enableCors: options.enableCors !== false,
      enableLogging: options.enableLogging !== false,
      enableRateLimit: options.enableRateLimit !== false,
      ...options
    };

    return validated;
  }

  /**
   * Get module generation summary
   * @param {string} moduleName - Nama module
   * @param {string} databaseType - Tipe database
   * @returns {Object} Generation summary
   */
  static getGenerationSummary(moduleName, databaseType) {
    const workingDir = ConfigReader.getWorkingDirectory();
    const moduleFilePath = path.join(workingDir, 'src', 'modules', `${moduleName}.js`);

    return {
      moduleName: moduleName,
      databaseType: databaseType,
      filePath: moduleFilePath,
      exists: fs.existsSync(moduleFilePath),
      fileInfo: fs.existsSync(moduleFilePath) ? FileUtils.getFileInfo(moduleFilePath) : null,
      relativePath: path.relative(workingDir, moduleFilePath)
    };
  }

  /**
   * Check if module dapat di-generate
   * @param {string} moduleName - Nama module
   * @param {Object} options - Generation options
   * @returns {Object} Check result
   */
  static canGenerateModule(moduleName, options = {}) {
    const result = {
      canGenerate: true,
      warnings: [],
      blockers: []
    };

    try {
      const workingDir = ConfigReader.getWorkingDirectory();
      const moduleFilePath = path.join(workingDir, 'src', 'modules', `${moduleName}.js`);

      // Check if file exists dan force option
      if (fs.existsSync(moduleFilePath) && !options.force) {
        result.warnings.push('Module file already exists, use force option to overwrite');
      }

      // Check write permissions
      const modulesDir = path.join(workingDir, 'src', 'modules');
      try {
        fs.accessSync(modulesDir, fs.constants.W_OK);
      } catch (permError) {
        result.blockers.push('No write permission to modules directory');
        result.canGenerate = false;
      }

      // Check disk space (basic check)
      try {
        const stats = fs.statSync(workingDir);
        // This is a simple check, in production you might want more sophisticated disk space checking
      } catch (spaceError) {
        result.warnings.push('Could not check disk space');
      }

    } catch (error) {
      result.blockers.push(`Error checking generation prerequisites: ${error.message}`);
      result.canGenerate = false;
    }

    return result;
  }

  /**
   * Generate module dengan comprehensive error handling
   * @param {string} moduleName - Nama module
   * @param {string} databaseType - Tipe database
   * @param {Object} options - Generation options
   * @returns {Object} Generation result
   */
  static generateModuleWithResult(moduleName, databaseType = 'postgres', options = {}) {
    const result = {
      success: false,
      moduleName: moduleName,
      databaseType: databaseType,
      filePath: null,
      backupCreated: false,
      warnings: [],
      errors: []
    };

    try {
      // Validate prerequisites
      const checkResult = this.canGenerateModule(moduleName, options);
      result.warnings.push(...checkResult.warnings);

      if (!checkResult.canGenerate) {
        result.errors.push(...checkResult.blockers);
        return result;
      }

      // Validate options
      const validatedOptions = this.validateGenerationOptions(options);

      // Generate module
      const generated = this.createMainModule(moduleName, databaseType, validatedOptions);

      if (generated) {
        result.success = true;
        const summary = this.getGenerationSummary(moduleName, databaseType);
        result.filePath = summary.filePath;
        result.backupCreated = validatedOptions.createBackup && summary.exists;
      }

    } catch (error) {
      result.errors.push(error.message);
      console.error(`Module generation failed: ${error.message}`);
    }

    return result;
  }
}

module.exports = MainModuleGenerator;
