import { readFile, writeFile, rename, unlink } from 'fs/promises';

/**
 * Write or update an environment variable in a .env file
 * 
 * Uses atomic write pattern (temp file + rename) to prevent corruption
 * if process crashes during write.
 * 
 * ⚠️ **SECURITY WARNING**: This function stores values in PLAINTEXT.
 * Never use for production secrets. Use environment variables,
 * secret managers (AWS Secrets Manager, Vault), or encrypted files.
 * 
 * **Thread Safety**: Not safe for concurrent writes to the same file.
 * Multiple processes writing simultaneously may cause race conditions.
 * 
 * **Format Assumptions**: Assumes KEY=VALUE format without quotes or inline comments.
 * 
 * @param filePath - Path to the .env file
 * @param key - Environment variable key (uppercase recommended)
 * @param value - Environment variable value (stored as-is)
 * 
 * @example
 * ```typescript
 * // Create new variable
 * await writeEnvVar('.env', 'DATABASE_URL', 'postgresql://localhost/mydb');
 * 
 * // Update existing variable
 * await writeEnvVar('.env', 'DATABASE_URL', 'postgresql://localhost/newdb');
 * 
 * // Result is idempotent
 * await writeEnvVar('.env', 'API_KEY', 'abc123');
 * await writeEnvVar('.env', 'API_KEY', 'abc123'); // No change
 * ```
 */
export async function writeEnvVar(
  filePath: string,
  key: string,
  value: string,
): Promise<void> {
  let content = '';
  
  try {
    content = await readFile(filePath, 'utf-8');
  } catch (error) {
    // File doesn't exist, will create it
    if ((error as NodeJS.ErrnoException).code !== 'ENOENT') {
      throw error;
    }
  }

  const lines = content.split('\n');
  const keyPattern = new RegExp(`^${escapeRegExp(key)}=`);
  let found = false;

  // Remove trailing empty string from split (if content ended with \n)
  if (lines.length > 0 && lines[lines.length - 1] === '') {
    lines.pop();
  }

  const updatedLines = lines.map(line => {
    if (keyPattern.test(line)) {
      found = true;
      return `${key}=${value}`;
    }
    return line;
  });

  if (!found) {
    updatedLines.push(`${key}=${value}`);
  }

  // Join with newlines and add single trailing newline
  const newContent = updatedLines.join('\n') + '\n';
  
  // Atomic write: temp file + rename
  const tempPath = `${filePath}.tmp.${process.pid}`;
  
  try {
    await writeFile(tempPath, newContent, 'utf-8');
    await rename(tempPath, filePath);
  } catch (error) {
    // Clean up temp file on error
    try {
      await unlink(tempPath);
    } catch {
      // Ignore cleanup errors
    }
    throw error;
  }
}

/**
 * Escape special regex characters in a string
 */
function escapeRegExp(str: string): string {
  return str.replace(/[.*+?^${}()|[\]\\]/g, '\\$&');
}
