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

/**
 * Generator untuk submodule (endpoint) files
 */
class SubmoduleGenerator {

  /**
   * Generate submodule file
   * @param {string} moduleName - Nama module
   * @param {string} endpointName - Nama endpoint
   * @param {Object} processedPayload - Processed payload object
   * @param {boolean} forceOverwrite - Apakah menimpa file yang sudah ada
   * @param {string} databaseType - Tipe database
   * @returns {boolean} True jika berhasil
   */
  static createSubmoduleFile(moduleName, endpointName, processedPayload, forceOverwrite = false, databaseType = 'postgres') {
    try {
      console.log(``);
      console.log(`Generating submodule: ${moduleName}/${endpointName} (${databaseType})`);

      // Setup directories
      const subModulesDir = path.join(ConfigReader.getWorkingDirectory(), 'src', 'modules', moduleName);
      FileUtils.ensureDirectoryExists(subModulesDir);

      const subModuleFilePath = path.join(subModulesDir, `${endpointName}.js`);

      // Check if file exists
      if (fs.existsSync(subModuleFilePath) && !forceOverwrite) {
        console.log(`Submodule ${endpointName}.js already exists. Use --force=true to overwrite.`);
        return false;
      }

      // Generate submodule content
      const subModuleContent = this.generateSubmoduleContent(moduleName, endpointName, processedPayload, databaseType);

      // Write submodule file tanpa backup (archive system digunakan sebagai gantinya)
      FileUtils.writeFileWithBackup(subModuleFilePath, subModuleContent, false);

      console.log(`Submodule ${endpointName}.js generated successfully`);
      return true;

    } catch (error) {
      console.error(`Error generating submodule ${moduleName}/${endpointName}:`, error.message);
      throw error;
    }
  }

  /**
   * Generate submodule content based on database type
   * @param {string} moduleName - Nama module
   * @param {string} endpointName - Nama endpoint
   * @param {Object} payload - Processed payload object
   * @param {string} databaseType - Tipe database
   * @returns {string} Generated submodule content
   */
  static generateSubmoduleContent(moduleName, endpointName, payload, databaseType) {
    try {
      // Try Oracle template first if specified
      if (databaseType === 'sqlite') {
        const sqliteContent = this.generateSqliteSubmoduleContent(moduleName, endpointName, payload);
        if (sqliteContent) {
          console.log(`Using SQLite-specific template for ${endpointName} submodule`);
          return sqliteContent;
        } else {
          console.log(`SQLite template not available, falling back to PostgreSQL template`);
        }
      }

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

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

      // Default PostgreSQL template
      return this.generatePostgresSubmoduleContent(moduleName, endpointName, payload);

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

  /**
   * Generate Oracle submodule content
   * @param {string} moduleName - Nama module
   * @param {string} endpointName - Nama endpoint
   * @param {Object} payload - Processed payload object
   * @returns {string|null} Oracle submodule content atau null
   */
  static generateOracleSubmoduleContent(moduleName, endpointName, payload) {
    try {
      const oracleUtils = this.loadOracleUtils();
      if (oracleUtils && oracleUtils.createOracleSubmoduleTemplate) {
        const content = oracleUtils.createOracleSubmoduleTemplate(moduleName, endpointName, payload);
        if (content && content.trim().length > 0) {
          return content;
        }
      }
      return null;
    } catch (error) {
      console.warn(`Oracle submodule template not available: ${error.message}`);
      return null;
    }
  }

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

  /**
   * Generate SQLite submodule content
   * @param {string} moduleName - Nama module
   * @param {string} endpointName - Nama endpoint
   * @param {Object} payload - Processed payload object
   * @returns {string|null} SQLite submodule content atau null
   */
  static generateSqliteSubmoduleContent(moduleName, endpointName, payload) {
    try {
      const sqliteUtils = this.loadSqliteUtils();
      if (sqliteUtils && sqliteUtils.createSqliteSubmoduleTemplate) {
        const content = sqliteUtils.createSqliteSubmoduleTemplate(moduleName, endpointName, payload);
        if (content && content.trim().length > 0) {
          return content;
        }
      }
      return null;
    } catch (error) {
      console.warn(`SQLite submodule template not available: ${error.message}`);
      return null;
    }
  }

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

  /**
   * Generate MySQL submodule content
   * @param {string} moduleName - Nama module
   * @param {string} endpointName - Nama endpoint
   * @param {Object} payload - Processed payload object
   * @returns {string|null} MySQL submodule content atau null
   */
  static generateMysqlSubmoduleContent(moduleName, endpointName, payload) {
    try {
      const mysqlUtils = this.loadMysqlUtils();
      if (mysqlUtils && mysqlUtils.createMysqlSubmoduleTemplate) {
        const content = mysqlUtils.createMysqlSubmoduleTemplate(moduleName, endpointName, payload);
        if (content && content.trim().length > 0) {
          return content;
        }
      }
      return null;
    } catch (error) {
      console.warn(`MySQL submodule template not available: ${error.message}`);
      return null;
    }
  }

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

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

  /**
   * Generate PostgreSQL submodule content
   * @param {string} moduleName - Nama module
   * @param {string} endpointName - Nama endpoint
   * @param {Object} payload - Processed payload object
   * @returns {string|null} PostgreSQL submodule content atau null
   */
  static generatePostgresSubmoduleContent(moduleName, endpointName, payload) {
    try {
      const postgresUtils = this.loadPostgresUtils();
      if (postgresUtils && postgresUtils.createPostgresSubmoduleTemplate) {
        const content = postgresUtils.createPostgresSubmoduleTemplate(moduleName, endpointName, payload);
        if (content && content.trim().length > 0) {
          return content;
        }
      }
      return null;
    } catch (error) {
      console.warn(`PostgreSQL submodule template not available: ${error.message}`);
      return null;
    }
  }

  /**
   * Get enabled actions dari payload
   * @param {Object} payload - Processed payload object
   * @returns {Array} Array enabled actions
   */
  static getEnabledActions(payload) {
    if (!payload.action || typeof payload.action !== 'object') {
      return [];
    }

    return Object.entries(payload.action)
      .filter(([, enabled]) => enabled)
      .map(([action]) => action);
  }

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

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

  /**
   * Validate submodule generation options
   * @param {Object} options - Generation options
   * @returns {Object} Validated options
   */
  static validateSubmoduleOptions(options = {}) {
    return {
      forceOverwrite: Boolean(options.forceOverwrite || options.force),
      createBackup: options.createBackup !== false,
      includeValidation: options.includeValidation !== false,
      includeErrorHandling: options.includeErrorHandling !== false,
      includeLogging: options.includeLogging !== false,
      ...options
    };
  }

  /**
   * Generate submodule dengan comprehensive result
   * @param {string} moduleName - Nama module
   * @param {string} endpointName - Nama endpoint
   * @param {Object} processedPayload - Processed payload object
   * @param {boolean} forceOverwrite - Force overwrite
   * @param {string} databaseType - Database type
   * @returns {Object} Generation result
   */
  static generateSubmoduleWithResult(moduleName, endpointName, processedPayload, forceOverwrite = false, databaseType = 'postgres') {
    const result = {
      success: false,
      moduleName: moduleName,
      endpointName: endpointName,
      databaseType: databaseType,
      filePath: null,
      backupCreated: false,
      endpointsGenerated: [],
      warnings: [],
      errors: []
    };

    try {
      // Get enabled actions
      const enabledActions = this.getEnabledActions(processedPayload);

      const generated = this.createSubmoduleFile(moduleName, endpointName, processedPayload, forceOverwrite, databaseType);

      if (generated) {
        result.success = true;
        result.endpointsGenerated = enabledActions;
        const summary = this.getGenerationSummary(moduleName, endpointName);
        result.filePath = summary.filePath;
        result.backupCreated = forceOverwrite && summary.exists;

        // Add endpoint URLs untuk reference
        result.endpointUrls = enabledActions.map(action => `/api/${moduleName}/${endpointName}/${action}`);
      }

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

    return result;
  }

  /**
   * Generate comprehensive generation report
   * @param {string} moduleName - Nama module
   * @param {string} endpointName - Nama endpoint
   * @param {Object} processedPayload - Processed payload object
   * @param {string} databaseType - Database type
   * @returns {Object} Comprehensive report
   */
  static generateComprehensiveReport(moduleName, endpointName, processedPayload, databaseType) {
    const enabledActions = this.getEnabledActions(processedPayload);
    const summary = this.getGenerationSummary(moduleName, endpointName);

    return {
      module: {
        name: moduleName,
        endpoint: endpointName,
        database: databaseType,
        table: processedPayload.tableName
      },
      files: {
        submodule: summary,
        exists: summary.exists
      },
      actions: {
        enabled: enabledActions,
        count: enabledActions.length,
        endpoints: enabledActions.map(action => `/api/${moduleName}/${endpointName}/${action}`)
      },
      payload: {
        fieldCount: processedPayload.fieldName ? processedPayload.fieldName.length : 0,
        hasAdvancedQueries: !!(processedPayload.advancedQueries && Object.keys(processedPayload.advancedQueries).length > 0),
        hasFilters: !!(processedPayload.filters && processedPayload.filters.length > 0),
        features: processedPayload._metadata?.features || []
      },
      generation: {
        timestamp: new Date().toISOString(),
        generator: 'SubmoduleGenerator v1.0.0'
      }
    };
  }
}

module.exports = SubmoduleGenerator;
