<?php
/**
 * SmartThink3 LMS - Database Configuration
 * 
 * This file contains database connection settings and configuration
 * for the SmartThink3 Learning Management System.
 */

// Database Configuration
define('DB_HOST', 'localhost');
define('DB_NAME', 'smartthink');
define('DB_USER', 'root');
define('DB_PASS', 'pass');
define('DB_CHARSET', 'utf8mb4');

// Application Configuration
define('APP_NAME', 'SmartThink');
define('APP_VERSION', '1.0.0');
define('APP_URL', 'http://localhost/smartthink');
define('APP_ENV', 'development'); // development, staging, production

// Security Configuration
define('JWT_SECRET', 'your-super-secret-jwt-key-change-in-production');
define('ENCRYPTION_KEY', 'your-32-character-encryption-key');
define('HASH_COST', 12);

// Email Configuration
define('SMTP_HOST', 'smtp.gmail.com');
define('SMTP_PORT', 587);
define('SMTP_USERNAME', 'your-email@gmail.com');
define('SMTP_PASSWORD', 'your-app-password');
define('SMTP_FROM_EMAIL', 'noreply@smartthink.com');
define('SMTP_FROM_NAME', 'SmartThink');

// File Upload Configuration
define('UPLOAD_MAX_SIZE', 10485760); // 10MB in bytes
define('ALLOWED_FILE_TYPES', ['jpg', 'jpeg', 'png', 'gif', 'pdf', 'doc', 'docx', 'mp4', 'avi', 'mov']);
define('UPLOAD_PATH', __DIR__ . '/../uploads/');

// WhatsApp Configuration
define('WHATSAPP_API_URL', 'https://graph.facebook.com/v18.0/');
define('WHATSAPP_PHONE_ID', 'your-whatsapp-phone-id');
define('WHATSAPP_ACCESS_TOKEN', 'your-whatsapp-access-token');
define('WHATSAPP_WEBHOOK_URL', APP_URL . '/api/whatsapp/webhook');

// Payment Configuration
define('STRIPE_PUBLISHABLE_KEY', 'pk_test_your-stripe-publishable-key');
define('STRIPE_SECRET_KEY', 'sk_test_your-stripe-secret-key');
define('PAYPAL_CLIENT_ID', 'your-paypal-client-id');
define('PAYPAL_CLIENT_SECRET', 'your-paypal-client-secret');
// Paystack configuration (set test keys for development)
define('PAYSTACK_PUBLIC_KEY', 'pk_test_your-paystack-public-key');
define('PAYSTACK_SECRET_KEY', 'sk_test_your-paystack-secret-key');

// Regional Configuration
define('DEFAULT_REGION', 'usa');
define('SUPPORTED_REGIONS', serialize(['usa', 'europe', 'africa']));

// Session Configuration
define('SESSION_LIFETIME', 7200); // 2 hours in seconds
define('SESSION_PATH', '/');
define('SESSION_DOMAIN', '');
define('SESSION_SECURE', false); // Set to true in production with HTTPS
define('SESSION_HTTPONLY', true);

// Cache Configuration
define('CACHE_DRIVER', 'file'); // file, redis, memcached
define('CACHE_PREFIX', 'smartthink_');
define('CACHE_LIFETIME', 3600); // 1 hour

// Logging Configuration
define('LOG_PATH', __DIR__ . '/../logs/');
define('LOG_LEVEL', 'INFO'); // DEBUG, INFO, WARNING, ERROR, CRITICAL
define('LOG_MAX_FILES', 30);

// API Configuration
define('API_VERSION', 'v1');
define('API_RATE_LIMIT', 100); // requests per hour
define('API_TIMEOUT', 30); // seconds

// Feature Flags
define('FEATURE_GEOLOCATION', true);
define('FEATURE_WHATSAPP', true);
define('FEATURE_AI_RECOMMENDATIONS', true);
define('FEATURE_GAMIFICATION', true);
define('FEATURE_CERTIFICATES', true);

// Error Reporting
if (APP_ENV === 'development') {
    error_reporting(E_ALL);
    ini_set('display_errors', 1);
} else {
    error_reporting(E_ALL & ~E_DEPRECATED & ~E_STRICT);
    ini_set('display_errors', 0);
}

// Timezone
date_default_timezone_set('UTC');

// Character Set
ini_set('default_charset', 'UTF-8');

// Start Session
if (session_status() === PHP_SESSION_NONE) {
    session_set_cookie_params([
        'lifetime' => SESSION_LIFETIME,
        'path' => SESSION_PATH,
        'domain' => SESSION_DOMAIN,
        'secure' => SESSION_SECURE,
        'httponly' => SESSION_HTTPONLY,
        'samesite' => 'Lax'
    ]);
    session_start();
}

/**
 * Database Connection Class
 */
class Database {
    private static $instance = null;
    private $connection;
    
    /**
     * Get database instance (Singleton pattern)
     */
    public static function getInstance() {
        if (self::$instance === null) {
            self::$instance = new self();
        }
        return self::$instance;
    }
    
    /**
     * Private constructor to prevent direct instantiation
     */
    private function __construct() {
        try {
            $dsn = "mysql:host=" . DB_HOST . ";dbname=" . DB_NAME . ";charset=" . DB_CHARSET;
            $options = [
                PDO::ATTR_ERRMODE => PDO::ERRMODE_EXCEPTION,
                PDO::ATTR_DEFAULT_FETCH_MODE => PDO::FETCH_ASSOC,
                PDO::ATTR_EMULATE_PREPARES => false,
                PDO::ATTR_PERSISTENT => true
            ];
            
            $this->connection = new PDO($dsn, DB_USER, DB_PASS, $options);
        } catch (PDOException $e) {
            if (APP_ENV === 'development') {
                die("Database connection failed: " . $e->getMessage());
            } else {
                die("Database connection failed. Please try again later.");
            }
        }
    }
    
    /**
     * Get database connection
     */
    public function getConnection() {
        return $this->connection;
    }
    
    /**
     * Execute query with prepared statements
     */
    public function query($sql, $params = []) {
        try {
            $stmt = $this->connection->prepare($sql);
            $stmt->execute($params);
            return $stmt;
        } catch (PDOException $e) {
            $this->logError($e->getMessage(), $sql, $params);
            throw $e;
        }
    }
    
    /**
     * Get single record
     */
    public function get($sql, $params = []) {
        $stmt = $this->query($sql, $params);
        return $stmt->fetch();
    }
    
    /**
     * Get multiple records
     */
    public function getAll($sql, $params = []) {
        $stmt = $this->query($sql, $params);
        return $stmt->fetchAll();
    }
    
    /**
     * Insert record
     */
    public function insert($table, $data) {
        $columns = implode(', ', array_keys($data));
        $placeholders = implode(', ', array_fill(0, count($data), '?'));
        $values = array_values($data);
        
        $sql = "INSERT INTO $table ($columns) VALUES ($placeholders)";
        $this->query($sql, $values);
        
        return $this->connection->lastInsertId();
    }

    /**
     * Wrapper to return last insert id (convenience)
     */
    public function getLastInsertId() {
        return $this->connection->lastInsertId();
    }
    
    /**
     * Update record
     */
    public function update($table, $data, $where, $whereParams = []) {
        $setClause = [];
        $values = [];
        
        foreach ($data as $column => $value) {
            $setClause[] = "$column = ?";
            $values[] = $value;
        }
        
        $setClause = implode(', ', $setClause);
        $values = array_merge($values, $whereParams);
        
        $sql = "UPDATE $table SET $setClause WHERE $where";
        $stmt = $this->query($sql, $values);
        
        return $stmt->rowCount();
    }
    
    /**
     * Delete record
     */
    public function delete($table, $where, $params = []) {
        $sql = "DELETE FROM $table WHERE $where";
        $stmt = $this->query($sql, $params);
        
        return $stmt->rowCount();
    }
    
    /**
     * Begin transaction
     */
    public function beginTransaction() {
        return $this->connection->beginTransaction();
    }
    
    /**
     * Commit transaction
     */
    public function commit() {
        return $this->connection->commit();
    }
    
    /**
     * Rollback transaction
     */
    public function rollback() {
        return $this->connection->rollback();
    }
    
    /**
     * Log database errors
     */
    private function logError($message, $sql, $params) {
        $logMessage = sprintf(
            "[%s] Database Error: %s | SQL: %s | Params: %s\n",
            date('Y-m-d H:i:s'),
            $message,
            $sql,
            json_encode($params)
        );
        
        error_log($logMessage, 3, LOG_PATH . 'database.log');
    }
    
    /**
     * Prevent cloning of singleton instance
     */
    private function __clone() {}
    
    /**
     * Prevent unserialization of singleton instance
     */
    public function __wakeup() {
        throw new Exception("Cannot unserialize singleton");
    }
}

/**
 * Utility Functions
 */

/**
 * Generate secure random token
 */
function generateToken($length = 32) {
    return bin2hex(random_bytes($length / 2));
}

/**
 * Hash password securely
 */
function hashPassword($password) {
    return password_hash($password, PASSWORD_ARGON2ID, ['cost' => HASH_COST]);
}

/**
 * Verify password
 */
function verifyPassword($password, $hash) {
    return password_verify($password, $hash);
}

/**
 * Sanitize input data
 */
function sanitize($data) {
    if (is_array($data)) {
        return array_map('sanitize', $data);
    }
    return htmlspecialchars(trim($data), ENT_QUOTES, 'UTF-8');
}

/**
 * Validate email
 */
function validateEmail($email) {
    return filter_var($email, FILTER_VALIDATE_EMAIL) !== false;
}

/**
 * Format date for database
 */
function formatDate($date = null) {
    if ($date === null) {
        return date('Y-m-d H:i:s');
    }
    return date('Y-m-d H:i:s', strtotime($date));
}

/**
 * Get client IP address
 */
function getClientIP() {
    $ipKeys = ['HTTP_CLIENT_IP', 'HTTP_X_FORWARDED_FOR', 'HTTP_X_FORWARDED', 'HTTP_FORWARDED_FOR', 'HTTP_FORWARDED', 'REMOTE_ADDR'];
    
    foreach ($ipKeys as $key) {
        if (array_key_exists($key, $_SERVER) === true) {
            foreach (explode(',', $_SERVER[$key]) as $ip) {
                $ip = trim($ip);
                if (filter_var($ip, FILTER_VALIDATE_IP, FILTER_FLAG_NO_PRIV_RANGE | FILTER_FLAG_NO_RES_RANGE) !== false) {
                    return $ip;
                }
            }
        }
    }
    
    return $_SERVER['REMOTE_ADDR'] ?? '0.0.0.0';
}

/**
 * Get user agent
 */
function getUserAgent() {
    return $_SERVER['HTTP_USER_AGENT'] ?? 'Unknown';
}

function sendEmail($to, $subject, $htmlMessage) {
    $headers = [];
    $headers[] = 'MIME-Version: 1.0';
    $headers[] = 'Content-type: text/html; charset=UTF-8';
    $fromEmail = SMTP_FROM_EMAIL ?? 'noreply@example.com';
    $fromName = SMTP_FROM_NAME ?? APP_NAME;
    $headers[] = 'From: ' . sprintf('%s <%s>', $fromName, $fromEmail);

    $headersString = implode("\r\n", $headers);

    return @mail($to, $subject, $htmlMessage, $headersString);
}

/**
 * Redirect to URL
 */
function redirect($url, $statusCode = 302) {
    header("Location: $url", true, $statusCode);
    exit;
}

/**
 * Set flash message
 */
function setFlashMessage($type, $message) {
    $_SESSION['flash'][$type] = $message;
}

/**
 * Get flash message
 */
function getFlashMessage($type) {
    if (isset($_SESSION['flash'][$type])) {
        $message = $_SESSION['flash'][$type];
        unset($_SESSION['flash'][$type]);
        return $message;
    }
    return null;
}

/**
 * Check if user is logged in
 */
function isLoggedIn() {
    return isset($_SESSION['user_id']) && !empty($_SESSION['user_id']);
}

/**
 * Get current user ID
 */
function getCurrentUserId() {
    return $_SESSION['user_id'] ?? null;
}

/**
 * Get current user data
 */
function getCurrentUser() {
    if (isLoggedIn()) {
        $db = Database::getInstance();
        return $db->get("SELECT * FROM users WHERE id = ?", [getCurrentUserId()]);
    }
    return null;
}

/**
 * Require login
 */
function requireLogin() {
    if (!isLoggedIn()) {
        setFlashMessage('error', 'Please login to access this page.');
        // Always send users to the central LMS login page so this works
        // consistently from both LMS and CMS contexts.
        redirect(APP_URL . '/lms/login.php');
    }
}

/**
 * Check user role
 */
function hasRole($role) {
    // Primary source of truth for the current role is stored in the session
    // by User::createSession(). This avoids relying on a non-existent `role`
    // column on the users table.
    if (isset($_SESSION['role']) && $_SESSION['role']) {
        $currentRole = $_SESSION['role'];

        // Treat super_admin as having admin privileges as well.
        if ($role === 'admin') {
            return in_array($currentRole, ['admin', 'super_admin'], true);
        }

        return $currentRole === $role;
    }

    return false;
}

function hasPermission($permission, $expectedValue = true) {
    if (!isset($_SESSION['permissions']) || $_SESSION['permissions'] === null) {
        return false;
    }

    $permissions = $_SESSION['permissions'];
    if (is_string($permissions)) {
        $decoded = json_decode($permissions, true);
        $permissions = is_array($decoded) ? $decoded : [];
    }

    if (!is_array($permissions)) {
        return false;
    }

    if (isset($permissions['all']) && $permissions['all'] === true) {
        return true;
    }

    if (!array_key_exists($permission, $permissions)) {
        return false;
    }

    if ($expectedValue === null) {
        return true;
    }

    return $permissions[$permission] === $expectedValue;
}

function requireAnyRole($roles) {
    requireLogin();

    $currentRole = $_SESSION['role'] ?? null;
    if (!$currentRole) {
        setFlashMessage('error', 'Access denied.');
        redirect(APP_URL . '/lms/dashboard.php');
    }

    $roles = is_array($roles) ? $roles : [$roles];
    if (!in_array($currentRole, $roles, true)) {
        setFlashMessage('error', 'Access denied.');
        redirect(APP_URL . '/lms/dashboard.php');
    }
}

function requirePermission($permission, $expectedValue = true) {
    requireLogin();

    if (!hasPermission($permission, $expectedValue)) {
        setFlashMessage('error', 'Access denied.');
        redirect(APP_URL . '/lms/dashboard.php');
    }
}

/**
 * Build a region filter for queries where applicable.
 * Returns an array: ['clause' => 'table.region = ?', 'params' => ['africa']]
 * If no region restriction applies, returns ['clause' => '1=1', 'params' => []].
 */
function currentRegionFilter($alias = null) {
    $role = $_SESSION['role'] ?? null;
    $permissions = $_SESSION['permissions'] ?? null;

    // Decode permissions if stored as JSON string
    if (is_string($permissions)) {
        $decoded = json_decode($permissions, true);
        $permissions = is_array($decoded) ? $decoded : [];
    }

    if ($role === 'regional_admin') {
        $region = null;
        if (is_array($permissions) && isset($permissions['manage_region']) && $permissions['manage_region']) {
            $region = $permissions['manage_region'];
        }
        if (!$region) {
            $region = $_SESSION['region'] ?? DEFAULT_REGION;
        }
        $prefix = $alias ? ($alias . '.') : '';
        return ['clause' => $prefix . 'region = ?', 'params' => [$region]];
    }

    return ['clause' => '1=1', 'params' => []];
}

/**
 * Require specific role
 */
function requireRole($role) {
    if (!hasRole($role)) {
        setFlashMessage('error', 'You do not have permission to access this page.');
        redirect('dashboard.php');
    }
}

/**
 * Load configuration from file
 */
function loadConfig($file) {
    if (file_exists($file)) {
        return parse_ini_file($file, true);
    }
    return [];
}

/**
 * Debug function (development only)
 */
function debug($var, $die = false) {
    if (APP_ENV === 'development') {
        echo '<pre>';
        print_r($var);
        echo '</pre>';
        if ($die) {
            die();
        }
    }
}

// Initialize flash messages
if (!isset($_SESSION['flash'])) {
    $_SESSION['flash'] = [];
}

// Auto-load helper files
$helperFiles = [
    __DIR__ . '/helpers/security.php',
    __DIR__ . '/helpers/validation.php',
    __DIR__ . '/helpers/email.php',
    __DIR__ . '/helpers/file.php'
];

foreach ($helperFiles as $file) {
    if (file_exists($file)) {
        require_once $file;
    }
}
?>
