<?php
/**
 * Configuration Manager with Fallback Support
 * Handles environment variables with fallback to database/config files
 */

class ConfigManager {
    private static $instance = null;
    private $config = [];
    private $loaded = false;
    
    private function __construct() {
        try {
            $this->loadConfiguration();
        } catch (Exception $e) {
            // In production, show user-friendly error
            if (isset($_SERVER['HTTP_HOST'])) {
                // Web request - show maintenance page
                http_response_code(503);
                die('Service temporarily unavailable. Please try again later.');
            } else {
                // CLI - show detailed error
                throw $e;
            }
        }
    }
    
    public static function getInstance() {
        if (self::$instance === null) {
            self::$instance = new self();
        }
        return self::$instance;
    }
    
    public static function forceReload() {
        self::$instance = null;
        return self::getInstance();
    }
    
    private function loadConfiguration() {
        if ($this->loaded) {
            return;
        }
        
        // Method 1: Try database configuration FIRST (prioritize database over environment)
        if ($this->loadFromDatabase()) {
            error_log('Config: Loaded from database (preferred)');
            $this->loaded = true;
            return;
        }
        
        // Method 2: Fallback to environment variables
        if ($this->loadFromEnvironment()) {
            error_log('Config: Loaded from environment variables (fallback)');
            $this->loaded = true;
            return;
        }
        
        // Method 3: Secure failure - no hardcoded fallbacks
        $this->loadFromFallback(); // This will log the error
        
        throw new Exception('Configuration loading failed. Please check .env file and database connection.');
    }
    
    private function loadFromEnvironment() {
        try {
            // Try to load environment file
            $envPath = __DIR__ . '/.env';
            if (file_exists($envPath) && is_readable($envPath)) {
                $this->parseEnvFile($envPath);
            }
            
            // Check if required variables are available
            $required = ['DB_HOST', 'DB_NAME', 'DB_USER', 'DB_PASS', 'STRIPE_PUBLISHABLE_KEY', 'STRIPE_SECRET_KEY'];
            foreach ($required as $key) {
                if (!$this->get($key)) {
                    return false;
                }
            }
            
            return true;
        } catch (Exception $e) {
            error_log('Environment loading failed: ' . $e->getMessage());
            return false;
        }
    }
    
    private function parseEnvFile($envPath) {
        $lines = file($envPath, FILE_IGNORE_NEW_LINES | FILE_SKIP_EMPTY_LINES);
        
        foreach ($lines as $line) {
            if (strpos(trim($line), '#') === 0) {
                continue; // Skip comments
            }
            
            if (strpos($line, '=') !== false) {
                list($key, $value) = explode('=', $line, 2);
                $key = trim($key);
                $value = trim($value);
                
                // Remove quotes
                if (preg_match('/^"(.*)"$/', $value, $matches)) {
                    $value = $matches[1];
                } elseif (preg_match("/^'(.*)'$/", $value, $matches)) {
                    $value = $matches[1];
                }
                
                $this->config[$key] = $value;
                
                // Also set as environment variable
                if (!getenv($key)) {
                    putenv("{$key}={$value}");
                    $_ENV[$key] = $value;
                }
            }
        }
    }
    
    private function loadFromDatabase() {
        try {
            // Only try database if we have basic environment variables
            $host = $this->get('DB_HOST');
            $name = $this->get('DB_NAME'); 
            $user = $this->get('DB_USER');
            $pass = $this->get('DB_PASS');
            
            if (!$host || !$name || !$user || !$pass) {
                return false; // Can't connect without credentials
            }
            
            $pdo = new PDO(
                "mysql:host={$host};dbname={$name}",
                $user,
                $pass,
                [PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION]
            );
            
            $stmt = $pdo->prepare("SELECT setting_key, setting_value FROM admin_settings WHERE setting_key IN (?, ?, ?, ?)");
            $stmt->execute(['brevoApiKey', 'stripePublishableKey', 'stripeSecretKey', 'stripeWebhookSecret']);
            
            $settings = $stmt->fetchAll(PDO::FETCH_KEY_PAIR);
            
            // Database settings loaded successfully
            
            if (!empty($settings)) {
                // Map database settings to environment variables
                $mapping = [
                    'brevoApiKey' => 'BREVO_API_KEY',
                    'stripePublishableKey' => 'STRIPE_PUBLISHABLE_KEY',
                    'stripeSecretKey' => 'STRIPE_SECRET_KEY',
                    'stripeWebhookSecret' => 'STRIPE_WEBHOOK_SECRET'
                ];
                
                foreach ($mapping as $dbKey => $envKey) {
                    if (isset($settings[$dbKey])) {
                        $this->config[$envKey] = $settings[$dbKey];
                    }
                }
                
                // Database config already loaded from environment variables
                
                return true;
            }
            
            return false;
        } catch (Exception $e) {
            error_log('Database config loading failed: ' . $e->getMessage());
            return false;
        }
    }
    
    private function loadFromFallback() {
        // NO FALLBACK CREDENTIALS - Fail securely
        // If environment variables and database are both unavailable,
        // the application should fail rather than expose hardcoded secrets
        error_log('CRITICAL: No configuration source available. Check environment variables and database.');
        return false;
    }
    
    public function get($key, $default = null) {
        // Check loaded config first (database values loaded during construction)
        if (isset($this->config[$key])) {
            return $this->config[$key];
        }
        
        // Fallback to environment variables
        $envValue = getenv($key);
        if ($envValue !== false) {
            return $envValue;
        }
        
        return $default;
    }
    
    public function getRequired($key) {
        $value = $this->get($key);
        if ($value === null || $value === '') {
            throw new Exception("Required configuration key '{$key}' is not set");
        }
        return $value;
    }
    

}

// Helper functions for backward compatibility
function getConfig($key, $default = null) {
    return ConfigManager::getInstance()->get($key, $default);
}

function getRequiredConfig($key) {
    return ConfigManager::getInstance()->getRequired($key);
}


?>
