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

/**
 * Utility untuk membaca konfigurasi aplikasi
 */
class ConfigReader {
  /**
   * Deteksi apakah running di Bun runtime
   */
  static get isBun() {
    return typeof Bun !== 'undefined';
  }

  /**
   * Deteksi apakah running sebagai Bun compiled binary
   *
   * Detection logic:
   * 1. Harus running di Bun runtime
   * 2. process.argv[1] akan mengandung path /$bunfs/ (virtual filesystem Bun)
   *    ATAU process.execPath tidak mengandung 'bun' di folder name (karena sudah jadi standalone exe)
   * 3. Alternatif: cek apakah execPath adalah file exe standalone (bukan bun.exe)
   */
  static get isBunCompiled() {
    if (!this.isBun) return false;

    // Method 1: Cek apakah argv[1] mengandung $bunfs (Bun virtual filesystem)
    const hasVirtualFS = process.argv[1] && process.argv[1].includes('$bunfs');

    // Method 2: Cek apakah execPath bukan path ke bun binary standar
    // Saat compiled, execPath akan mengarah ke binary standalone kita
    const execPathLower = process.execPath.toLowerCase();
    const isBunStandardPath = execPathLower.includes('bun') &&
                              (execPathLower.endsWith('bun') || execPathLower.endsWith('bun.exe'));

    // Method 3: Cek apakah nama executable mengandung 'restforge'
    const isRestforgeBinary = execPathLower.includes('restforge');

    return hasVirtualFS || isRestforgeBinary || !isBunStandardPath;
  }

  /**
   * Deteksi environment - Compiled binary atau script
   * @deprecated Gunakan isCompiledBinary sebagai gantinya
   */
  static get isPkg() {
    return this.isCompiledBinary;
  }

  /**
   * Deteksi apakah running sebagai compiled binary (Bun)
   */
  static get isCompiledBinary() {
    return this.isBunCompiled;
  }

  /**
   * Deteksi apakah running sebagai script (Node.js atau Bun)
   * @deprecated Gunakan isScript sebagai gantinya
   */
  static get isNodeScript() {
    return this.isScript;
  }

  /**
   * Deteksi apakah running sebagai script (Node.js atau Bun)
   */
  static get isScript() {
    return !this.isCompiledBinary;
  }

  /**
   * Fungsi untuk mendapatkan working directory yang benar
   * Selalu menggunakan current working directory user (project root)
   * @returns {string} Working directory path
   */
  static getWorkingDirectory() {
    return process.cwd();
  }

  /**
   * Setup environment berdasarkan compiled binary atau script
   */
  static setupEnvironment() {
    // Suppress experimental warnings untuk compiled binary environment
    if (this.isCompiledBinary) {
      process.removeAllListeners('warning');
    }

    if (process.env.NODE_ENV !== 'production') {
      const workingDir = this.getWorkingDirectory();
      console.error(`Working directory: ${workingDir}`);
      console.error(`Is Bun: ${this.isBun}`);
      console.error(`Is compiled binary: ${this.isCompiledBinary}`);
    }
  }

  /**
   * Fungsi untuk membaca konfigurasi dari file create-module.env
   * @returns {Object} Konfigurasi yang telah diparse
   */
  static readConfig() {
    // Setup environment terlebih dahulu
    this.setupEnvironment();
    
    const workingDir = this.getWorkingDirectory();
    const configPath = path.join(workingDir, 'config', 'create-module.env');
    
    if (!fs.existsSync(configPath)) {
      console.error('Error: File config/create-module.env not found!');
      console.error(`Expected path: ${configPath}`);
      process.exit(1);
    }
    
    try {
      const configContent = fs.readFileSync(configPath, 'utf8');
      const config = {};
      
      configContent.split('\n').forEach(line => {
        line = line.trim();
        if (line && !line.startsWith('#')) {
          const equalIndex = line.indexOf('=');
          if (equalIndex > 0) {
            const key = line.substring(0, equalIndex).trim();
            const value = line.substring(equalIndex + 1).trim();
            if (key && value) {
              config[key] = value;
            }
          }
        }
      });
      
      // Validasi konfigurasi yang diperlukan
      const requiredFields = ['EMAIL', 'APP', 'SECRET_KEY'];
      const missingFields = requiredFields.filter(field => !config[field]);
      
      if (missingFields.length > 0) {
        console.error('Error: Incomplete configuration in create-module.env!');
        console.error(`Missing fields: ${missingFields.join(', ')}`);
        console.error('Make sure the file contains EMAIL, APP, and SECRET_KEY');
        process.exit(1);
      }
      
      // Log konfigurasi yang berhasil dimuat (tanpa secret key)
      console.log('Configuration loaded successfully:');
      console.log(`   Email: ${config.EMAIL}`);
      console.log(`   App: ${config.APP}`);
      console.log(`   Secret Key: ${'*'.repeat(config.SECRET_KEY.length)}`);
      
      return config;
    } catch (error) {
      console.error('Error reading configuration file:', error.message);
      console.error(`Config path: ${configPath}`);
      process.exit(1);
    }
  }

  /**
   * Fungsi untuk membaca konfigurasi opsional dari file tertentu
   * @param {string} filename - Nama file konfigurasi (dengan ekstensi)
   * @returns {Object|null} Konfigurasi yang berhasil dibaca atau null jika gagal
   */
  static readOptionalConfig(filename) {
    try {
      const workingDir = this.getWorkingDirectory();
      const configPath = path.join(workingDir, 'config', filename);
      
      if (!fs.existsSync(configPath)) {
        return null;
      }
      
      const configContent = fs.readFileSync(configPath, 'utf8');
      const config = {};
      
      configContent.split('\n').forEach(line => {
        line = line.trim();
        if (line && !line.startsWith('#')) {
          const equalIndex = line.indexOf('=');
          if (equalIndex > 0) {
            const key = line.substring(0, equalIndex).trim();
            const value = line.substring(equalIndex + 1).trim();
            if (key && value) {
              config[key] = value;
            }
          }
        }
      });
      
      return config;
    } catch (error) {
      console.warn(`Warning: Error membaca file ${filename}:`, error.message);
      return null;
    }
  }

  /**
   * Validasi apakah semua path yang diperlukan ada
   * @returns {Object} Status validasi path
   */
  static validatePaths() {
    const workingDir = this.getWorkingDirectory();
    const requiredPaths = {
      config: path.join(workingDir, 'config'),
      src: path.join(workingDir, 'src'),
      modules: path.join(workingDir, 'src', 'modules'),
      models: path.join(workingDir, 'src', 'models'),
      payload: path.join(workingDir, 'payload'),
      metadata: path.join(workingDir, 'metadata')
    };

    const pathStatus = {};
    
    for (const [name, pathLocation] of Object.entries(requiredPaths)) {
      pathStatus[name] = {
        path: pathLocation,
        exists: fs.existsSync(pathLocation),
        required: ['config', 'src'].includes(name) // config dan src wajib ada
      };
    }

    return {
      workingDir,
      paths: pathStatus,
      allRequiredExists: Object.values(pathStatus)
        .filter(p => p.required)
        .every(p => p.exists)
    };
  }

  /**
   * Membuat direktori yang diperlukan jika belum ada
   * @param {Array<string>} directories - Array nama direktori yang akan dibuat
   */
  static ensureDirectories(directories = ['src', 'payload', 'metadata']) {
    const workingDir = this.getWorkingDirectory();
    
    directories.forEach(dir => {
      const dirPath = path.join(workingDir, dir);
      if (!fs.existsSync(dirPath)) {
        try {
          fs.mkdirSync(dirPath, { recursive: true });
          console.log(`Directory ${dir} created successfully: ${dirPath}`);
        } catch (error) {
          console.error(`Error creating directory ${dir}:`, error.message);
          throw error;
        }
      }
    });
  }
}

module.exports = ConfigReader;