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

/**
 * Manager untuk metadata modul dan endpoint
 */
class MetadataManager {

  /**
   * Get metadata file path untuk module
   * @param {string} moduleName - Nama module
   * @returns {string} Path file metadata
   */
  static getMetadataPath(moduleName) {
    const workingDir = ConfigReader.getWorkingDirectory();
    const metadataDir = path.join(workingDir, 'metadata');
    
    // Ensure metadata directory exists
    FileUtils.ensureDirectoryExists(metadataDir, false);
    
    return path.join(metadataDir, `${moduleName}.json`);
  }

  /**
   * Get global metadata file path
   * @returns {string} Path file global metadata
   */
  static getGlobalMetadataPath() {
    const workingDir = ConfigReader.getWorkingDirectory();
    const metadataDir = path.join(workingDir, 'metadata');
    
    FileUtils.ensureDirectoryExists(metadataDir, false);
    
    return path.join(metadataDir, 'global.json');
  }

  /**
   * Membaca metadata modul
   * @param {string} moduleName - Nama module
   * @returns {Object} Metadata object
   */
  static readModuleMetadata(moduleName) {
    const metadataPath = this.getMetadataPath(moduleName);
    
    if (!fs.existsSync(metadataPath)) {
      // Buat metadata awal jika belum ada
      const initialMetadata = this.createInitialModuleMetadata(moduleName);
      this.writeModuleMetadata(moduleName, initialMetadata);
      return initialMetadata;
    }
    
    try {
      const metadataContent = fs.readFileSync(metadataPath, 'utf8');
      const metadata = JSON.parse(metadataContent);
      
      // Validasi dan upgrade metadata jika perlu
      return this.validateAndUpgradeMetadata(metadata, moduleName);
    } catch (error) {
      console.warn(`Warning: Error reading metadata for ${moduleName}, creating new`);
      console.warn(`   Error: ${error.message}`);
      
      // Backup file yang corrupt
      if (fs.existsSync(metadataPath)) {
        const backupPath = `${metadataPath}.corrupt.${Date.now()}`;
        fs.copyFileSync(metadataPath, backupPath);
        console.log(`Metadata corrupt di-backup ke: ${path.basename(backupPath)}`);
      }
      
      const initialMetadata = this.createInitialModuleMetadata(moduleName);
      this.writeModuleMetadata(moduleName, initialMetadata);
      return initialMetadata;
    }
  }

  /**
   * Membuat initial metadata untuk module
   * @param {string} moduleName - Nama module
   * @returns {Object} Initial metadata object
   */
  static createInitialModuleMetadata(moduleName) {
    return {
      version: '2.0.0',
      moduleName: moduleName,
      createdAt: new Date().toISOString(),
      updatedAt: new Date().toISOString(),
      databaseType: null,
      endpoints: {},
      statistics: {
        totalEndpoints: 0,
        endpointsByType: {},
        lastGenerated: null
      },
      config: {
        autoBackup: false,
        maxBackups: 5
      }
    };
  }

  /**
   * Validasi dan upgrade metadata ke versi terbaru jika perlu
   * @param {Object} metadata - Metadata object
   * @param {string} moduleName - Nama module
   * @returns {Object} Validated/upgraded metadata
   */
  static validateAndUpgradeMetadata(metadata, moduleName) {
    let upgraded = false;
    
    // Ensure required fields exist
    if (!metadata.version) {
      metadata.version = '1.0.0';
      upgraded = true;
    }
    
    if (!metadata.moduleName) {
      metadata.moduleName = moduleName;
      upgraded = true;
    }
    
    if (!metadata.createdAt) {
      metadata.createdAt = new Date().toISOString();
      upgraded = true;
    }
    
    if (!metadata.updatedAt) {
      metadata.updatedAt = new Date().toISOString();
      upgraded = true;
    }
    
    if (!metadata.endpoints) {
      metadata.endpoints = {};
      upgraded = true;
    }
    
    if (!metadata.statistics) {
      metadata.statistics = {
        totalEndpoints: Object.keys(metadata.endpoints).length,
        endpointsByType: this.calculateEndpointsByType(metadata.endpoints),
        lastGenerated: null
      };
      upgraded = true;
    }
    
    if (!metadata.config) {
      metadata.config = {
        autoBackup: false,
        maxBackups: 5
      };
      upgraded = true;
    }
    
    // Version-specific upgrades
    if (this.compareVersions(metadata.version, '2.0.0') < 0) {
      metadata = this.upgradeToV2(metadata);
      upgraded = true;
    }
    
    if (upgraded) {
      metadata.version = '2.0.0';
      metadata.updatedAt = new Date().toISOString();
      this.writeModuleMetadata(moduleName, metadata);
      console.log(`Metadata for ${moduleName} upgraded to version ${metadata.version}`);
    }
    
    return metadata;
  }

  /**
   * Upgrade metadata ke versi 2.0.0
   * @param {Object} metadata - Metadata object versi lama
   * @returns {Object} Upgraded metadata
   */
  static upgradeToV2(metadata) {
    // Add new fields dan struktur untuk v2.0.0
    const upgraded = { ...metadata };
    
    // Update endpoint structure jika perlu
    for (const [endpointName, endpointData] of Object.entries(upgraded.endpoints)) {
      if (!endpointData.version) {
        endpointData.version = '2.0.0';
      }
      
      if (!endpointData.statistics) {
        endpointData.statistics = {
          timesGenerated: 1,
          lastGenerated: endpointData.updatedAt || endpointData.createdAt,
          lastModified: endpointData.updatedAt || endpointData.createdAt
        };
      }
    }
    
    return upgraded;
  }

  /**
   * Compare two version strings
   * @param {string} version1 - First version
   * @param {string} version2 - Second version
   * @returns {number} -1 if v1 < v2, 0 if equal, 1 if v1 > v2
   */
  static compareVersions(version1, version2) {
    const v1parts = version1.split('.').map(Number);
    const v2parts = version2.split('.').map(Number);
    
    for (let i = 0; i < Math.max(v1parts.length, v2parts.length); i++) {
      const v1part = v1parts[i] || 0;
      const v2part = v2parts[i] || 0;
      
      if (v1part < v2part) return -1;
      if (v1part > v2part) return 1;
    }
    
    return 0;
  }

  /**
   * Menulis metadata modul
   * @param {string} moduleName - Nama module
   * @param {Object} metadata - Metadata object
   * @returns {boolean} True jika berhasil
   */
  static writeModuleMetadata(moduleName, metadata) {
    const metadataPath = this.getMetadataPath(moduleName);
    
    try {
      // Update timestamp
      metadata.updatedAt = new Date().toISOString();
      
      // Create backup if enabled
      if (metadata.config && metadata.config.autoBackup && fs.existsSync(metadataPath)) {
        this.createMetadataBackup(metadataPath, metadata.config.maxBackups || 5);
      }
      
      // Write metadata dengan formatting yang rapi
      const metadataJson = JSON.stringify(metadata, null, 2);
      fs.writeFileSync(metadataPath, metadataJson, 'utf8');
      
      console.log(``);
      console.log(`Metadata for module ${moduleName} successfully updated`);
      
      // Update global metadata
      this.updateGlobalMetadata();
      
      return true;
    } catch (error) {
      console.error(`Error writing metadata for ${moduleName}:`, error.message);
      throw new Error(`Failed to write metadata: ${error.message}`);
    }
  }

  /**
   * Create backup untuk metadata file
   * @param {string} metadataPath - Path file metadata
   * @param {number} maxBackups - Maximum number of backups to keep
   */
  static createMetadataBackup(metadataPath, maxBackups = 5) {
    try {
      const timestamp = new Date().toISOString().replace(/[:.]/g, '-');
      const backupPath = `${metadataPath}.backup.${timestamp}`;
      
      fs.copyFileSync(metadataPath, backupPath);
      
      // Cleanup old backups
      this.cleanupOldMetadataBackups(path.dirname(metadataPath), path.basename(metadataPath), maxBackups);
    } catch (error) {
      console.warn(`Warning: Gagal membuat backup metadata:`, error.message);
    }
  }

  /**
   * Cleanup old metadata backups
   * @param {string} directory - Directory yang berisi backup files
   * @param {string} baseFileName - Base filename untuk metadata
   * @param {number} maxBackups - Maximum number of backups to keep
   */
  static cleanupOldMetadataBackups(directory, baseFileName, maxBackups = 5) {
    try {
      if (!fs.existsSync(directory)) {
        return;
      }

      const files = fs.readdirSync(directory);
      const backupFiles = files
        .filter(file => file.startsWith(`${baseFileName}.backup.`))
        .map(file => ({
          name: file,
          path: path.join(directory, file),
          mtime: fs.statSync(path.join(directory, file)).mtime
        }))
        .sort((a, b) => b.mtime - a.mtime); // Sort by modification time, newest first

      // Keep only maxBackups newest files
      if (backupFiles.length > maxBackups) {
        const filesToDelete = backupFiles.slice(maxBackups);
        
        for (const file of filesToDelete) {
          fs.unlinkSync(file.path);
        }
        
        if (filesToDelete.length > 0) {
          console.log(`🗑️  Cleaned up ${filesToDelete.length} old metadata backups`);
        }
      }
    } catch (error) {
      console.warn(`Warning: Error cleaning up metadata backups:`, error.message);
    }
  }

  /**
   * Update metadata untuk endpoint yang dibuat
   * @param {string} moduleName - Nama module
   * @param {string} endpointName - Nama endpoint
   * @param {Object} payload - Payload object
   * @param {string} databaseType - Tipe database
   * @returns {boolean} True jika berhasil
   */
  static updateEndpointMetadata(moduleName, endpointName, payload, databaseType = 'postgres') {
    try {
      const metadata = this.readModuleMetadata(moduleName);
      const now = new Date().toISOString();
      
      // Check if endpoint already exists
      const isUpdate = endpointName in metadata.endpoints;
      
      // Create/update endpoint metadata
      metadata.endpoints[endpointName] = {
        version: '2.0.0',
        type: 'module',
        createdAt: isUpdate ? metadata.endpoints[endpointName].createdAt : now,
        updatedAt: now,
        path: `src/modules/${moduleName}/${endpointName}.js`,
        modelPath: `src/models/${moduleName}/${endpointName}.js`,
        tableName: payload.tableName,
        databaseType: databaseType,
        actions: payload.action || {},
        fieldCount: payload.fieldName ? payload.fieldName.length : 0,
        hasAdvancedQueries: !!(payload.advancedQueries && Object.keys(payload.advancedQueries).length > 0),
        hasNestedQueries: !!(payload.nestedQueries && payload.nestedQueries.length > 0),
        hasFilters: !!(payload.filters && payload.filters.length > 0),
        hasSearchColumns: !!(payload.searchColumns && payload.searchColumns.length > 0),
        statistics: {
          timesGenerated: isUpdate ? (metadata.endpoints[endpointName].statistics?.timesGenerated || 0) + 1 : 1,
          lastGenerated: now,
          lastModified: now
        }
      };
      
      // Set database type untuk module jika belum ada
      if (!metadata.databaseType) {
        metadata.databaseType = databaseType;
      }
      
      // Update module statistics
      metadata.statistics = {
        totalEndpoints: Object.keys(metadata.endpoints).length,
        endpointsByType: this.calculateEndpointsByType(metadata.endpoints),
        lastGenerated: now
      };
      
      // Write updated metadata
      this.writeModuleMetadata(moduleName, metadata);
      
      console.log(`Metadata for endpoint ${endpointName} successfully ${isUpdate ? 'updated' : 'created'}`);
      
      return true;
    } catch (error) {
      console.error(`Error updating endpoint metadata:`, error.message);
      throw error;
    }
  }

  /**
   * Update metadata untuk dashboard endpoint. Paralel ke updateEndpointMetadata,
   * tapi struktur metadata berbeda — dashboard tidak punya tableName/actions/fields,
   * melainkan widget aggregation info.
   *
   * @param {string} moduleName - Nama project, mis. 'mini-inventory'
   * @param {string} dashboardName - Nama dashboard lengkap dengan prefix 'dash-', mis. 'dash-sales'
   * @param {Object} payload - Payload dashboard yang sudah lulus DashboardValidator
   * @param {string} databaseType - Tipe database (default 'postgres')
   * @returns {boolean} True jika berhasil
   */
  static updateDashboardMetadata(moduleName, dashboardName, payload, databaseType = 'postgres') {
    try {
      const metadata = this.readModuleMetadata(moduleName);
      const now = new Date().toISOString();
      const endpointKey = dashboardName;

      const isUpdate = endpointKey in metadata.endpoints;

      metadata.endpoints[endpointKey] = {
        version: '2.0.0',
        type: 'dashboard',
        createdAt: isUpdate ? metadata.endpoints[endpointKey].createdAt : now,
        updatedAt: now,
        path: `src/modules/${moduleName}/${dashboardName}.js`,
        databaseType: databaseType,
        widgetCount: Array.isArray(payload.widgets) ? payload.widgets.length : 0,
        widgetIds: Array.isArray(payload.widgets) ? payload.widgets.map((w) => w && w.id).filter(Boolean) : [],
        paramsContract: {
          keyCount: payload.params ? Object.keys(payload.params).length : 0,
          keys: payload.params ? Object.keys(payload.params) : []
        },
        statistics: {
          timesGenerated: isUpdate ? ((metadata.endpoints[endpointKey].statistics && metadata.endpoints[endpointKey].statistics.timesGenerated) || 0) + 1 : 1,
          lastGenerated: now,
          lastModified: now
        }
      };

      // Set database type untuk module jika belum ada
      if (!metadata.databaseType) {
        metadata.databaseType = databaseType;
      }

      // Update module statistics (reuse existing helper)
      metadata.statistics = {
        totalEndpoints: Object.keys(metadata.endpoints).length,
        endpointsByType: this.calculateEndpointsByType(metadata.endpoints),
        lastGenerated: now
      };

      this.writeModuleMetadata(moduleName, metadata);

      console.log(`Metadata for dashboard ${endpointKey} successfully ${isUpdate ? 'updated' : 'created'}`);

      return true;
    } catch (error) {
      console.error(`Error updating dashboard metadata:`, error.message);
      throw error;
    }
  }

  // ========================================
  // WORKBENCH METADATA
  // ========================================

  /**
   * Get workbench metadata file path untuk module
   * @param {string} moduleName - Nama module
   * @returns {string} Path file workbench metadata ({moduleName}-workbench.json)
   */
  static getWorkbenchMetadataPath(moduleName) {
    const workingDir = ConfigReader.getWorkingDirectory();
    const metadataDir = path.join(workingDir, 'metadata');
    FileUtils.ensureDirectoryExists(metadataDir, false);
    return path.join(metadataDir, `${moduleName}-workbench.json`);
  }

  /**
   * Write workbench metadata ke file
   * @param {string} moduleName - Nama module
   * @param {Object} metadata - Workbench metadata object
   */
  static writeWorkbenchMetadata(moduleName, metadata) {
    const filePath = this.getWorkbenchMetadataPath(moduleName);
    const json = JSON.stringify(metadata, null, 2);
    fs.writeFileSync(filePath, json, 'utf8');
  }

  /**
   * Update workbench metadata untuk endpoint atau processor
   * @param {string} moduleName - Nama module
   * @param {string} endpointName - Nama endpoint
   * @param {Object} payload - Payload object
   * @param {string} databaseType - Tipe database
   * @param {string} type - 'endpoint' atau 'processor'
   */
  static updateWorkbenchMetadata(moduleName, endpointName, payload, databaseType, type) {
    try {
      const filePath = this.getWorkbenchMetadataPath(moduleName);

      // Baca existing atau buat baru
      let metadata;
      if (fs.existsSync(filePath)) {
        metadata = JSON.parse(fs.readFileSync(filePath, 'utf8'));
      } else {
        metadata = {
          projectName: moduleName,
          databaseType: databaseType || 'postgres',
          endpoints: {},
          processors: {}
        };
      }

      // Update databaseType jika belum ada
      if (databaseType && !metadata.databaseType) {
        metadata.databaseType = databaseType;
      }

      // Konversi endpoint name ke display name (kebab-case → Title-Case)
      const displayName = endpointName
        .split('-')
        .map(w => w.charAt(0).toUpperCase() + w.slice(1))
        .join('-');

      if (type === 'endpoint') {
        const entry = {
          tableName: payload.tableName || '',
          displayName: displayName,
          action: payload.action || {},
          primaryKey: payload.primaryKey || '',
          fieldName: payload.fieldName || [],
          fieldValidation: payload.fieldValidation || [],
          samples: this.generateActionSamples(payload),
        };

        if (payload.components && payload.components.length > 0) {
          entry.components = payload.components;
        }

        metadata.endpoints[endpointName] = entry;
      }

      if (type === 'processor') {
        metadata.processors[endpointName] = {
          displayName: displayName,
          processor: payload.processor.map(proc => {
            const item = { name: proc.name, method: proc.method };
            if (proc.description) item.description = proc.description;
            if (proc.sql) item.sql = proc.sql;
            if (proc.request) item.request = proc.request;
            if (proc.response) item.response = proc.response;
            return item;
          })
        };
      }

      this.writeWorkbenchMetadata(moduleName, metadata);
      console.log(`Workbench metadata for ${type} ${endpointName} successfully updated`);
    } catch (error) {
      console.warn(`Warning: Failed to update workbench metadata: ${error.message}`);
    }
  }

  /**
   * Generate action samples untuk workbench metadata.
   * Reuse DemoGenerator.generateDummyData() untuk sample value.
   * @param {Object} payload - Payload object
   * @returns {Object} Samples per action
   */
  static generateActionSamples(payload) {
    try {
      const DemoGenerator = require('../../src/utils/demo-generator');
      const dummyData = DemoGenerator.generateDummyData(payload);

      const fieldNames = payload.fieldName || [];
      const pk = payload.primaryKey || 'id';
      const pkVal = dummyData[pk] || 'sample-id';

      // Update data: modifikasi beberapa value (logic dari DemoGenerator.createJsonPayloadFiles)
      const updateData = { ...dummyData };
      Object.keys(updateData).forEach(key => {
        if (key === pk) return;
        if (key.toLowerCase().includes('name') && !key.toLowerCase().includes('first') && !key.toLowerCase().includes('last')) {
          updateData[key] = 'Updated ' + updateData[key];
        } else if (key.toLowerCase().includes('first')) {
          updateData[key] = 'Jane';
        } else if (key.toLowerCase().includes('email')) {
          updateData[key] = 'updated@example.com';
        }
      });

      const searchBy = (payload.datatablesWhere && payload.datatablesWhere.length > 0 && payload.datatablesWhere[0] !== 'all')
        ? payload.datatablesWhere[0]
        : fieldNames[1] || fieldNames[0] || 'name';

      return {
        create: { ...dummyData },
        update: updateData,
        delete: { where: [{ key: pk, value: pkVal }] },
        get: { where: [{ key: pk, value: pkVal }], select: fieldNames },
        read: { page: 1, per_page: 10, search_value: '', search_by: searchBy },
        datatables: { draw: 1, start: 0, length: 10, search: { value: '' } },
        lookup: { select: fieldNames.slice(0, 2) },
      };
    } catch (error) {
      console.warn(`Warning: Failed to generate action samples: ${error.message}`);
      return {};
    }
  }

  /**
   * Calculate endpoints by type untuk statistics
   * @param {Object} endpoints - Endpoints object
   * @returns {Object} Statistics by type
   */
  static calculateEndpointsByType(endpoints) {
    const stats = {};
    
    for (const [endpointName, endpointData] of Object.entries(endpoints)) {
      const type = endpointData.type || 'unknown';
      stats[type] = (stats[type] || 0) + 1;
    }
    
    return stats;
  }

  /**
   * Update global metadata dengan informasi semua modules
   */
  static updateGlobalMetadata() {
    try {
      const workingDir = ConfigReader.getWorkingDirectory();
      const metadataDir = path.join(workingDir, 'metadata');
      
      if (!fs.existsSync(metadataDir)) {
        return;
      }
      
      const globalMetadataPath = this.getGlobalMetadataPath();
      const files = fs.readdirSync(metadataDir);
      const moduleFiles = files.filter(file => file.endsWith('.json') && file !== 'global.json');
      
      const globalStats = {
        version: '2.0.0',
        lastUpdated: new Date().toISOString(),
        totalModules: moduleFiles.length,
        totalEndpoints: 0,
        modules: {},
        databaseTypes: {},
        summary: {
          endpointsByAction: {},
          endpointsByDatabase: {},
          recentActivity: []
        }
      };
      
      // Process each module metadata
      for (const moduleFile of moduleFiles) {
        try {
          const moduleName = path.basename(moduleFile, '.json');
          const moduleMetadataPath = path.join(metadataDir, moduleFile);
          const moduleMetadata = JSON.parse(fs.readFileSync(moduleMetadataPath, 'utf8'));
          
          const moduleEndpoints = Object.keys(moduleMetadata.endpoints || {});
          globalStats.totalEndpoints += moduleEndpoints.length;
          
          globalStats.modules[moduleName] = {
            endpointCount: moduleEndpoints.length,
            databaseType: moduleMetadata.databaseType,
            lastUpdated: moduleMetadata.updatedAt,
            createdAt: moduleMetadata.createdAt
          };
          
          // Count database types
          if (moduleMetadata.databaseType) {
            globalStats.databaseTypes[moduleMetadata.databaseType] = 
              (globalStats.databaseTypes[moduleMetadata.databaseType] || 0) + 1;
          }
          
          // Process actions untuk summary
          for (const [endpointName, endpointData] of Object.entries(moduleMetadata.endpoints || {})) {
            if (endpointData.actions) {
              for (const [action, enabled] of Object.entries(endpointData.actions)) {
                if (enabled) {
                  globalStats.summary.endpointsByAction[action] = 
                    (globalStats.summary.endpointsByAction[action] || 0) + 1;
                }
              }
            }
            
            if (endpointData.databaseType) {
              globalStats.summary.endpointsByDatabase[endpointData.databaseType] = 
                (globalStats.summary.endpointsByDatabase[endpointData.databaseType] || 0) + 1;
            }
          }
          
        } catch (error) {
          console.warn(`Warning: Error processing module metadata ${moduleFile}:`, error.message);
        }
      }
      
      // Write global metadata
      fs.writeFileSync(globalMetadataPath, JSON.stringify(globalStats, null, 2), 'utf8');
      
    } catch (error) {
      console.warn(`Warning: Error updating global metadata:`, error.message);
    }
  }

  /**
   * Get module statistics
   * @param {string} moduleName - Nama module
   * @returns {Object|null} Module statistics atau null jika tidak ada
   */
  static getModuleStatistics(moduleName) {
    try {
      const metadata = this.readModuleMetadata(moduleName);
      
      const stats = {
        moduleName: metadata.moduleName,
        totalEndpoints: Object.keys(metadata.endpoints).length,
        createdAt: metadata.createdAt,
        lastUpdated: metadata.updatedAt,
        databaseType: metadata.databaseType,
        endpoints: []
      };
      
      // Process endpoint details
      for (const [endpointName, endpointData] of Object.entries(metadata.endpoints)) {
        const enabledActions = Object.entries(endpointData.actions || {})
          .filter(([, enabled]) => enabled)
          .map(([action]) => action);
          
        stats.endpoints.push({
          name: endpointName,
          tableName: endpointData.tableName,
          actions: enabledActions,
          fieldCount: endpointData.fieldCount || 0,
          hasAdvancedQueries: endpointData.hasAdvancedQueries || false,
          hasFilters: endpointData.hasFilters || false,
          lastGenerated: endpointData.statistics?.lastGenerated,
          timesGenerated: endpointData.statistics?.timesGenerated || 0
        });
      }
      
      return stats;
    } catch (error) {
      console.error(`Error getting module statistics for ${moduleName}:`, error.message);
      return null;
    }
  }

  /**
   * Get global statistics untuk semua modules
   * @returns {Object|null} Global statistics atau null jika error
   */
  static getGlobalStatistics() {
    try {
      const globalMetadataPath = this.getGlobalMetadataPath();
      
      if (!fs.existsSync(globalMetadataPath)) {
        this.updateGlobalMetadata();
      }
      
      const globalStats = JSON.parse(fs.readFileSync(globalMetadataPath, 'utf8'));
      return globalStats;
    } catch (error) {
      console.error(`Error getting global statistics:`, error.message);
      return null;
    }
  }

  /**
   * Remove endpoint dari metadata
   * @param {string} moduleName - Nama module
   * @param {string} endpointName - Nama endpoint
   * @returns {boolean} True jika berhasil
   */
  static removeEndpointMetadata(moduleName, endpointName) {
    try {
      const metadata = this.readModuleMetadata(moduleName);
      
      if (!(endpointName in metadata.endpoints)) {
        console.warn(`Warning: Endpoint ${endpointName} not found in metadata`);
        return false;
      }
      
      delete metadata.endpoints[endpointName];
      
      // Update statistics
      metadata.statistics = {
        totalEndpoints: Object.keys(metadata.endpoints).length,
        endpointsByType: this.calculateEndpointsByType(metadata.endpoints),
        lastGenerated: metadata.statistics.lastGenerated
      };
      
      this.writeModuleMetadata(moduleName, metadata);
      
      console.log(`Endpoint ${endpointName} removed from metadata successfully`);
      return true;
    } catch (error) {
      console.error(`Error removing endpoint metadata:`, error.message);
      return false;
    }
  }

  /**
   * Check apakah endpoint sudah ada dalam metadata
   * @param {string} moduleName - Nama module
   * @param {string} endpointName - Nama endpoint
   * @returns {boolean} True jika endpoint sudah ada
   */
  static endpointExists(moduleName, endpointName) {
    try {
      const metadata = this.readModuleMetadata(moduleName);
      return endpointName in metadata.endpoints;
    } catch (error) {
      console.warn(`Warning: Error checking endpoint existence:`, error.message);
      return false;
    }
  }

  /**
   * Get endpoint metadata
   * @param {string} moduleName - Nama module
   * @param {string} endpointName - Nama endpoint
   * @returns {Object|null} Endpoint metadata atau null jika tidak ada
   */
  static getEndpointMetadata(moduleName, endpointName) {
    try {
      const metadata = this.readModuleMetadata(moduleName);
      return metadata.endpoints[endpointName] || null;
    } catch (error) {
      console.error(`Error getting endpoint metadata:`, error.message);
      return null;
    }
  }

  /**
   * List semua modules yang ada
   * @returns {Array} Array nama modules
   */
  static listModules() {
    try {
      const workingDir = ConfigReader.getWorkingDirectory();
      const metadataDir = path.join(workingDir, 'metadata');
      
      if (!fs.existsSync(metadataDir)) {
        return [];
      }
      
      const files = fs.readdirSync(metadataDir);
      const moduleFiles = files.filter(file => file.endsWith('.json') && file !== 'global.json');
      
      return moduleFiles.map(file => path.basename(file, '.json'));
    } catch (error) {
      console.error(`Error listing modules:`, error.message);
      return [];
    }
  }

  /**
   * Export metadata untuk backup atau sharing
   * @param {string} moduleName - Nama module (optional, jika tidak diisi export semua)
   * @param {string} outputPath - Path output file
   * @returns {boolean} True jika berhasil
   */
  static exportMetadata(moduleName = null, outputPath = null) {
    try {
      const workingDir = ConfigReader.getWorkingDirectory();
      const defaultOutputPath = path.join(workingDir, `metadata-export-${Date.now()}.json`);
      const finalOutputPath = outputPath || defaultOutputPath;
      
      let exportData;
      
      if (moduleName) {
        // Export specific module
        exportData = {
          type: 'module',
          moduleName: moduleName,
          exportedAt: new Date().toISOString(),
          data: this.readModuleMetadata(moduleName)
        };
      } else {
        // Export all metadata
        const modules = this.listModules();
        const allModules = {};
        
        for (const module of modules) {
          allModules[module] = this.readModuleMetadata(module);
        }
        
        exportData = {
          type: 'global',
          exportedAt: new Date().toISOString(),
          globalStats: this.getGlobalStatistics(),
          modules: allModules
        };
      }
      
      fs.writeFileSync(finalOutputPath, JSON.stringify(exportData, null, 2), 'utf8');
      
      console.log(`Metadata exported successfully to: ${finalOutputPath}`);
      return true;
    } catch (error) {
      console.error(`Error exporting metadata:`, error.message);
      return false;
    }
  }

  /**
   * Show module summary dalam format yang readable
   * @param {string} moduleName - Nama module
   */
  static showModuleSummary(moduleName) {
    try {
      const stats = this.getModuleStatistics(moduleName);
      
      if (!stats) {
        console.log(`Module ${moduleName} not found`);
        return;
      }
      
      console.log(`\nModule: ${stats.moduleName}`);
      console.log(`📅 Created: ${new Date(stats.createdAt).toLocaleDateString()}`);
      console.log(`Last Updated: ${new Date(stats.lastUpdated).toLocaleDateString()}`);
      console.log(`💾 Database: ${stats.databaseType || 'Not specified'}`);
      console.log(`Total Endpoints: ${stats.totalEndpoints}`);
      
      if (stats.endpoints.length > 0) {
        console.log(`\nEndpoints:`);
        stats.endpoints.forEach(endpoint => {
          console.log(`   - ${endpoint.name} (${endpoint.tableName})`);
          console.log(`     Actions: ${endpoint.actions.join(', ')}`);
          console.log(`     Fields: ${endpoint.fieldCount}`);
          if (endpoint.hasAdvancedQueries) {
            console.log(`     Has Advanced Queries`);
          }
          if (endpoint.hasFilters) {
            console.log(`     Has Filters`);
          }
          console.log(`     Generated: ${endpoint.timesGenerated} times`);
          console.log('');
        });
      }
    } catch (error) {
      console.error(`Error showing module summary:`, error.message);
    }
  }

  /**
   * Get endpoint generation count untuk numbering archive files
   * @param {string} moduleName - Nama module
   * @param {string} endpointName - Nama endpoint
   * @returns {number} Generation count
   */
  static getEndpointGeneration(moduleName, endpointName) {
    try {
      const metadata = this.readModuleMetadata(moduleName);
      
      if (metadata.endpoints && metadata.endpoints[endpointName]) {
        return metadata.endpoints[endpointName].statistics?.timesGenerated || 0;
      }
      
      return 0;
    } catch (error) {
      console.warn(`Could not get generation count for ${moduleName}/${endpointName}:`, error.message);
      return 0;
    }
  }

  /**
   * Increment generation count untuk endpoint
   * @param {string} moduleName - Nama module
   * @param {string} endpointName - Nama endpoint
   * @returns {number} New generation count
   */
  static incrementEndpointGeneration(moduleName, endpointName) {
    try {
      const metadata = this.readModuleMetadata(moduleName);
      
      if (metadata.endpoints && metadata.endpoints[endpointName]) {
        const currentCount = metadata.endpoints[endpointName].statistics?.timesGenerated || 0;
        const newCount = currentCount + 1;
        
        metadata.endpoints[endpointName].statistics.timesGenerated = newCount;
        metadata.endpoints[endpointName].statistics.lastGenerated = new Date().toISOString();
        metadata.endpoints[endpointName].updatedAt = new Date().toISOString();
        metadata.updatedAt = new Date().toISOString();
        
        this.writeModuleMetadata(moduleName, metadata);
        
        return newCount;
      }
      
      return 1;
    } catch (error) {
      console.warn(`Could not increment generation count for ${moduleName}/${endpointName}:`, error.message);
      return 1;
    }
  }
}

module.exports = MetadataManager;